ElementUI el-checkbox实现全选反选单选

本文介绍如何在Vue应用中实现一个多选组,支持全选、反选和单选功能,同时确保提交表单时至少选择一种类型,且参数使用英文ID。展示了代码实现和交互细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、概述

先来看一下效果图

需求:

1. 每一种类型,可以全选,反选(一个都不选),单选(仅选一个或者多个)

2. 保存时,至少有一种类型,选择1个或多个。不能都不选,直接提交空表单。

3. 保存时,提交参数都是id,不能出现中文。

初始页面数据如下:

[{
    "groupId": 1,
    "groupName": "运动",
    "checkAll": false,
    "ischeckAll": [],
    "interestList": [{
        "name": "篮球",
        "tasteId": 10
    }, {
        "name": "足球",
        "tasteId": 11
    }, {
        "name": "乒乓球",
        "tasteId": 12
    }]
}, {
    "groupId": 2,
    "groupName": "棋类",
    "checkAll": false,
    "ischeckAll": [],
    "interestList": [{
        "name": "军旗",
        "tasteId": 14
    }, {
        "name": "象棋",
        "tasteId": 15
    }, {
        "name": "五子棋",
        "tasteId": 16
    }]
}]

提交参数格式如下:

{
    "interestList": [{
        "groupId": 1,
        "itemList": []
    }, {
        "groupId": 2,
        "itemList": [14]
    }]
}

注意:itemList是具体某一项的id,比如:足球。

二、代码实现

test.vue

<template>
  <div style="width:800px;margin-left: 10px;margin-top: 10px">
    <div>
      <span class="big_title">兴趣爱好</span>
    </div>
    <div class="div_space"></div>
    <div v-for="(parent,index) in groupList" :key="index">
      <div>
        <div class="div_space" v-if="index!=0"></div>
        <div class="titles">{{ parent.groupName }}</div>
        <div>
          <el-checkbox v-model="parent.checkAll" @change="selectAllFunc(parent.groupId,parent.checkAll)"
                       style="float: left;padding-right: 20px">全选
          </el-checkbox>
          <el-checkbox-group v-model="parent.ischeckAll">
            <el-checkbox @change="setCheck(parent.groupId)" v-for="(item,index2) in parent.interestList"
                         :value="item.tasteId" :label="item.tasteId" :key="item.tasteId">{{item.name}}
            </el-checkbox>
          </el-checkbox-group>
        </div>
      </div>
    </div>
    <div class="div_space"></div>
    <div>
      <button class="btn btn-primary" @click="form_validation()">保存</button>
      <button class="btn btn-cancel" style="margin-left: 5px;" >取消</button>
    </div>
  </div>
</template>
<script>
  export default {
    data() {
      return {
        groupList: [
          {
            groupId: 1,
            groupName: '运动',
            checkAll: false,
            ischeckAll: [],
            interestList: [
              {
                name: '篮球',
                tasteId: 10
              },
              {
                name: '足球',
                tasteId: 11
              },
              {
                name: '乒乓球',
                tasteId: 12
              }
            ],
          },
          {
            groupId: 2,
            groupName: '棋类',
            checkAll: false,
            ischeckAll: [],
            interestList: [
              {
                name: '军旗',
                tasteId: 14
              },
              {
                name: '象棋',
                tasteId: 15
              },
              {
                name: '五子棋',
                tasteId: 16
              }
            ],
          }
        ],
        params: {
          interestList:[]
        },
        // groupList: [],  // 所有电梯列表
      }
    },
    mounted() {
      //
      console.log("初始数据",JSON.stringify(this.groupList))
    },
    methods: {
      // 勾选全选动作
      selectAllFunc(id, checkAll) {
        // console.log("执行selectAllFunc", id, checkAll)
        // 遍历列表
        for (let val of this.groupList) {
          // 判断groupId
          if (val.groupId == id) {
            // 判断全选,如果checkAll为true,则遍历interestList,将tasteId填充到ischeckAll中
            // 否则为为空列表,注意:为空时,表示反选。
            val.ischeckAll = checkAll ? val.interestList.map(item => item.tasteId) : []
            // console.log("ischeckAll", val.ischeckAll)
          }
        }
        // console.log(this.groupList)
      },
      // 设置全选状态
      setCheck(id) {
        // console.log("执行setCheck", id)
        for (let val of this.groupList) {
          if (val.groupId == id) {
            // 判断已经选中的列表是否和选项列表数量一致,如果一致为true,否则为false
            val.checkAll = val.ischeckAll.length == val.interestList.length ? true : false
          }
        }
      },
      // 验证表单
      form_validation() {
        // 设置提交参数列表,遍历groupList,组合新的对象
        this.params.interestList = this.groupList.map(item => {
          return {
            groupId: item.groupId,
            itemList: item.ischeckAll
          }
        })
        // console.log(this.params.interestList)
        // 选择标志位
        let select_flag = false
        // 遍历提交参数列表
        for (let val of this.params.interestList) {
          // 判断列表长度,只要其中一组选择了,标准为true
          if (val.itemList.length > 0) {
            select_flag = true
          }
        }
        // 判断兴趣爱好至少选一个
        if (select_flag == false) {
          this.$message.error("兴趣爱好至少选一个")
          return false
        }
        // return false
        this.submit()
      },
      submit(){
        console.log("提交参数",JSON.stringify(this.params))
      }
    }
  }
</script>
<style scoped>
  .big_title {
    width: 172px;
    height: 22px;
    font-size: 16px;
    font-family: PingFangSC-Medium, PingFang SC;
    font-weight: 550;
    color: #333333;
    line-height: 22px;
  }

  .div_space {
    height: 15px;
  }
</style>
View Code

效果如下:

注意:当选择的选项都选中时,会自动勾选全选,否则不勾选。

### 解析 `el-checkbox-group` 组件单选导致全部中的原因 当使用 Element UI 的 `el-checkbox-group` 实现单选功能时,如果遇到点击一个项却触发了所有项被中的情况,通常是因为配置方式恰当造成的。具体来说,在上述场景下,问题可能源于对 `v-model` 和事件处理逻辑的设计当。 在给定的例子中,通过设置 `false-label` 和 `true-label` 属性来控制 checkbox 的状态转换是一个合理的尝试[^1]。然而,这并适用于所有的应用场景特别是当试图模拟单选行为的时候。对于希望达到类似 radio button 效果的情况,应该考虑调整组件的择机制以及如何管理内部的状态变化。 ### 提供解决方案 为了防止 `el-checkbox-group` 中的一个择影响其他所有项的状态,可以采取如下措施: #### 方法一:自定义数据结构与监听器 创建一个新的属性用于存储当前定值,并利用计算属性或方法动态更新视图层面上的表现形式。这样做的好处是可以更灵活地掌控每一个单独的checkbox的行为而必担心它们之间相互干扰。 ```html <template> <div> <!-- 使用radio样式 --> <el-radio-group v-model="selectedOption"> <el-radio-button label="0">显示</el-radio-button> <el-radio-button label="1">隐藏</el-radio-button> </el-radio-group> <!-- 或者继续沿用checkbox外观但改变其交互模式 --> <el-checkbox-group v-model="dummySelections" @change="handleChange"> <el-checkbox :label="'0'" disabled>{{ selectedOption === '0' ? '√ 显示' : '显示' }}</el-checkbox> <el-checkbox :label="'1'" disabled>{{ selectedOption === '1' ? '√ 隐藏' : '隐藏' }}</el-checkbox> </el-checkbox-group> </div> </template> <script> export default { data() { return { dummySelections: [], selectedOption: null, preItem: {} }; }, methods: { handleChange(val) { this.selectedOption = val[val.length - 1]; // 取最后一个作为新的择 this.dummySelections = [this.selectedOption]; this.preItem.picShow = this.selectedOption; } } }; </script> ``` 这种方法的核心在于引入了一个额外的数据字段 (`dummySelections`) 来保持界面的一致性,而真正代表用户意图的是另一个变量(`selectedOption`)。每当发生变更时,只允许最新的那个项生效并同步至后台或其他地方保存起来。 #### 方法二:直接替换为 Radio Button 考虑到实际需求是要实现类似于单选的效果,最简单的方式就是直接采用 `el-radio-group` 替代原有的 `el-checkbox-group` 。Radio buttons 天生就适合用来表示互斥的择关系,因此需要做太多额外的工作就能满足要求。 ```html <!-- 更改为radio组 --> <el-radio-group v-model="form.picShow" @change="(val)=>{preItem.picShow=val}"> <el-radio :label="'0'">显示</el-radio> <el-radio :label="'1'">隐藏</el-radio> </el-radio-group> ``` 这样做仅简化了代码复杂度,同时也避免了许多潜在的问题,比如意外全选等现象的发生。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值