前车之鉴: 适用于所有select选择框的 全选反选逻辑,如何只用单个change事件优雅完成

实际效果

1.1 效果展示

在这里插入图片描述

1.2 核心功能

  1. 区别网上其他思路,我这里不需要使用原生点击事件,将全选反选逻辑收敛在一个change事件上

此前已经看过一些全选逻辑同学尝试过后,会发现大部分是将全选的option单独定制,然后添加事件,确实可以实现目的,但是存在两个问题
A1: 全选逻辑和反选逻辑分开维护,方法太多维护成本高,不易debug
A2:自定义了全选事件需要使用原生@click.native事件,有些平台需要2次点击才能进行标签移除,交互体验就牺牲了

2. 全选选中,其他都选中,全选不选中,其他都不选
3. 除了全选都选中,则全选选中
4. 对于已经全选的标签,移除一个,全选自动移除

5. 提供调试思路、丰富的注释【热衷分享~~】


Show Code

<el-form-item label="上游服务节点:" prop="gray_server_hosts">
     <el-select v-model="currentSelectedInstanceList" @change="selfAdaptInstanceSelectAllEvent"
                  placeholder="请选择" multiple :disabled="isEdit">
                  <!-- <el-option  @click.native="handleSelectAll(chooseAllValue)" :label='chooseAllValue' :key="chooseAllValue" :value="chooseAllValue"></el-option> -->
        <el-option v-for="item in instanceObjectArray" :key="item.value" :label="item.label"  :value="item.value" />
    </el-select>
</el-form-item>
export default {
  name: "FlowSwitchManage",
  data() {
  	  // 动态数据,一般是对象数组
  	  instanceObjectArray: [],
  	  // 当前选中的数据,一般情况是普通数组
      currentSelectedInstanceList: [],
      // 非响应的数据,用于保留上一次选中数据情况
      preSelectOptions:[],
      // 给全选打标记,1 代表全选
      choose_all: 0,
      chooseAllValue: '全选',
  },
  methods:{
   selfAdaptInstanceSelectAllEvent(current) {
      console.log("自动响应", current, this.choose_all, this.currentSelectedInstanceList, this.instanceObjectArray)
      // 1.如果之前没有全选
      //  1.1 现在有全选,全部选上
      //  1.2 现在没有全选,但是数量和列表一致,全选选上
      // 2.如果之前有全选 
      //  2.1 现在还有全选,则移除的是普通选项,则一并移除全选
      //  2.2 移除的是全选,则清空
      if (!this.preSelectOptions.includes(this.chooseAllValue)) {
        if ((!current.includes(this.chooseAllValue) && current.length === this.instanceObjectArray.length - 1) || current.includes(this.chooseAllValue)) {
          this.choose_all = 1
          this.currentSelectedInstanceList = [...this.instanceObjectArray.map(option => option.value)]
        } 
      } else if (current.includes(this.chooseAllValue) ) {
        this.choose_all = 0
        this.currentSelectedInstanceList = this.currentSelectedInstanceList.filter(val => val !== this.chooseAllValue)
       } else if (!current.includes(this.chooseAllValue)) {
        this.choose_all = 0
        this.currentSelectedInstanceList = []
      }
      this.preSelectOptions = this.currentSelectedInstanceList
    },
  },
   watch: {
    // 'currentSelectedInstanceList' (newVal, oldVal) {
    //   console.log('监听instance变化', oldVal, '--->', newVal)
    //   this.selfAdaptInstanceSelectAllEvent()
    // } 两个方式都对
    // currentSelectedInstanceList: {
    //   handler(newVal, oldVal) {
    //     console.log('监听instance变化', oldVal, '--->', newVal)
    //     this.selfAdaptInstanceSelectAllEvent()
    //   },
    //   deep: true
    // }

  }  
}

Q & A

作为一名后端童鞋, 根据自己的踩坑经验总结得出该设计,也借鉴不少设计,基本的注释都有,通过详细的字段名应该比较清晰,这里在回答几个问题

1、preSelectOptions 的作用在于vue是响应式的,只要你对组件变更会立刻更新mode绑定的数据,这是为什么和网上其他思路不一样,只使用一个方法解决的核心所在,如果不保存上一次的快照数据那么是无法做到用1个方法处理
2. current 和 model绑定的模型currentSelectedInstanceList数据其实一样的,这里是el组件提供方便操作而已
3. choose_all 存在的价值在于你的业务是否需要精细化控制,一般场景可以忽略


彩蛋

如果使用蚂蚁的antd-design-vue框架,a-select如何使用

data和method 不用改变,直接迁移,html使用如下即可

<a-select style="width:200px"  :options="instanceObjectArray" v-model="currentSelectedInstanceList" @change="selfAdaptInstanceSelectAllEvent" placeholder="请选择" mode="multiple"/>
  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值