如何用Vue实现一个全选指令

最近用vue做了两个项目,都需要实现全选反选的功能,两个项目用了两种实现方法,第一个项目用vue的computed,第二个项目用指令来实现,用起来,发觉指令更加方便。

第一次做全选的时候是刚开始接触vue不久,全选的实现参考了知乎(链接:https://www.zhihu.com/question/37833194/answer/91812053)上的实现方法:

1、从服务器拿到数据,为每个item设置checked属性

2、计算选中的数量selectCount,如果选中的数量与selectItems的数量相等,则全选selectAll选中

3、点全选时,将每个item的checked属性置为true,反选时置为false,

4、每次selectItems的属性发生变化时,都将checked的为true的item放入数组checkedGroups中

下面为实现代码:


  1. //全选 
  2.   data: function() { 
  3.       return { 
  4.           selectItems: [],  // 从服务器拿到的数据 
  5.       } 
  6.   }, 
  7.   computed: { 
  8.       // 全选checkbox绑定的model 
  9.       selectAll: { 
  10.           get: function() { 
  11.               return this.selectCount == this.selectItems.length; 
  12.           }, 
  13.           set: function(value) { 
  14.               this.selectItems.forEach(function(item) { 
  15.                   item.checked = value; 
  16.               }); 
  17.               return value; 
  18.           } 
  19.       }, 
  20.       //选中的数量 
  21.       selectCount: { 
  22.           get: function() { 
  23.               var i = 0; 
  24.               this.selectItems.forEach(function(item) { 
  25.                   if (item.checked) { 
  26.                       i++; 
  27.                   } 
  28.               }); 
  29.               return i; 
  30.           } 
  31.       }, 
  32.       //选中的数组 
  33.       checkedGroups: { 
  34.           get: function() { 
  35.               var checkedGroups = []; 
  36.               this.selectItems.forEach(function(item) { 
  37.                   if (item.checked) { 
  38.                       checkedGroups.push(item); 
  39.                   } 
  40.               }); 
  41.               return checkedGroups; 
  42.           } 
  43.       } 
  44.   }  

这种方法用起来不太方便,首先是很难复用,每次要用到的时候都需要写一次computed,其次是selectAll、checkedGroups、selectItems都已经固定,不太灵活。

所以在这次项目中,我用vue的指令重新实现了全选的功能,directive的思路其实跟computed差不多,先上代码:


  1. export default { 
  2.     'check-all': { 
  3.         twoWay: true, 
  4.         params: ['checkData'], 
  5.         bind() { 
  6.             /** 
  7.              - 如果所有的列表的checked属性都为true,则选中全选框,否则不选中全选框 
  8.              */ 
  9.             this.vm.$watch(this.params.checkData, (checkData) => { 
  10.                 if (checkData.every((item) => item.checked)) { 
  11.                     this.set(true); 
  12.                 } else { 
  13.                     this.set(false); 
  14.                 } 
  15.             }, { deep: true }); 
  16.         }, 
  17.         // checkAll发生更改时 
  18.         update(checkAll) { 
  19.             /** 
  20.              - 如果全选框被选中,则将列表的所有checked属性转为true,否则转为false 
  21.              */ 
  22.             if (checkAll) { 
  23.                 this.vm[this.params.checkData].forEach((item) => { 
  24.                     item.checked = true; 
  25.                 }); 
  26.             } else { 
  27.                 this.vm[this.params.checkData].forEach((item) => { 
  28.                     item.checked = false; 
  29.                 }); 
  30.             } 
  31.         }, 
  32.     }, 
  33. };  

调用:


  1. <input type="checkbox" v-model="checkAll" v-check-all="checkAll" check-data="checkData"> 
  2.         <ul> 
  3.             <li v-for="item in checkData"> 
  4.                 <input type="checkbox" v-model="item.checked"> 
  5.                 {{item.text}} 
  6.             </li> 
  7.         </ul> 

先说说这样用的优点:

1、方便使用,在需要用的地方,写上v-check-all指令和check-data就可以

2、全选的model和数组名可以定制,用什么名字都可以,全选的model不想叫checkAll叫checkAllData也可以,数组不想叫checkData叫dataFromServer也可以。

在指令中,指定twoWay为true,就可以用this.set(value)来设置checkAll的值,用params接收绑定指令元素上的属性值checkData,也就是需要操作的数组。

用this.vm获取使用指令的上下文,调用上下文的$watch来监听checkData的变化,如果checkData全部选中,则设置checkAll为true,否则设置checkAll为false。

当指令值(checkAll)发生变化,如果为true,则将checkData的checked属性都设为true,否则为false。至此,一个全选的指令就完成了。

在做这个全选指令的时候,本来想用paramWatchers来监听checkData的变化的,但是发觉checkData变动时,并不会触发paramWatchers的回调,后来看了一下源码才发现,paramWatchers其实也是调用了$watch,但是不支持深度检测:


  1. Directive.prototype._setupParamWatcher = function (key, expression) { 
  2.   var self = this; 
  3.   var called = false; 
  4.   var unwatch = (this._scope || this.vm).$watch(expression, function (val, oldVal) { 
  5.     self.params[key] = val; 
  6.     // since we are in immediate mode, 
  7.     // only call the param change callbacks if this is not the first update. 
  8.     if (called) { 
  9.       var cb = self.paramWatchers && self.paramWatchers[key]; 
  10.       if (cb) { 
  11.         cb.call(self, val, oldVal); 
  12.       } 
  13.     } else { 
  14.       called = true; 
  15.     } 
  16.   }, { 
  17.     immediate: true, 
  18.     user: false 
  19.   });(this._paramUnwatchFns || (this._paramUnwatchFns = [])).push(unwatch); 
  20. };  

本人中途改行,入行1年出头,还有很多东西要学,有不对的地方,还请大家多多指教。为了勉励自己多些总结,开了个微信公众号(front-end-article),最近都在用vue做项目,近期应该会写一些关于vue的文章。有兴趣可以关注一下哦,或者投稿也可以,多多交流哈。

作者:对角另一面

来源:51CTO

时间: 2024-11-10 01:10:51

如何用Vue实现一个全选指令的相关文章

利用Vue.js指令实现全选功能_javascript技巧

因为刚开始接触vue不久,全选的实现参考了知乎上的实现方法:      1.从服务器拿到数据,为每个item设置checked属性      2.计算选中的数量selectCount,如果选中的数量与selectItems的数量相等,则全选selectAll选中      3.点全选时,将每个item的checked属性置为true,反选时置为false,      4.每次selectItems的属性发生变化时,都将checked的为true的item放入数组checkedGroups中 下面

只有一个复选框的全选处理

复选框 网页中经常需要动态的生成多个复选框,通常还有一个"全选"按纽用来选定全部复选框或者全部取消选定. 但需要注意的一个问题是当只剩下一个复选框的时候就无法使用复选框length属性,要单独把一个复选框的情况拿出来判断 <input name="btnAllSelect" type="Button" id="Button" value="全选" class="myButton"

Jquery 实现智能全选

做页面一直会遇到全选和全不选的问题,在网上什么一句话实现全选全不选,也有很多用js方法实现的. 但是好像都忽略了一个问题,全选的可以控制下面的列表,但是下面的列表不能控制上面的全选,所以我就写了个例子 思路,一个全选checkALl,其他为checkItem,如果checkAll,全选和全不选下面的checkItem肯定也是全不选   但是如果checkItem为有一个没有勾选,checkAll就不应该勾选,如果checkItem全勾选上,checkAll应该要变为是勾选上的 ok,看看我实现的

全选DataGrid里的复选框

datagrid|复选框 我们经常会在DataGrid里选择一组数据,然后批量操作,如果要全部操作的话需要一个全选的功能,如果你用这个全选按钮的服务器端事件来让DataGrid里复选框的全选的话,会多一次向服务器的回传,我们可以写一个js函数来简化这一步骤.其实DataGrid在客户端会生成一个html表格,表格的id属性就是DataGrid的ID,这个ID可以用ClientID获取,然后你的全选按钮也可以在后台编码里添加一个onclick属性来让他执行你写好的js代码,比如你声明了一个Data

Jquery实现智能全选(new)

做页面一直会遇到全选和全不选的问题,在网上什么一句话实现全选全不选,也有很多用js方法实 现的. 但是好像都忽略了一个问题,全选的可以控制下面的列表,但是下面的列表不能控制上面的全选, 所以我就写了个例子 思路,一个全选checkALl,其他为checkItem,如果checkAll,全选和全不选下面的checkItem肯定也 是全不选 但是如果checkItem为有一个没有勾选,checkAll就不应该勾选,如果checkItem全勾选上, checkAll应该要变为是勾选上的 ok,看看我实

jquery操作checkbox实现全选和取消全选_jquery

今天这样写了一个全选和取消全选的功能: 全选:$(":checkbox").attr("checked","checked"); 取消全选:$(":checkbox").removeAttr("checked"); 获取选中的:$(":checked[checked='checked']") 发现点全选可以,在点取消全选也可以,获取选中的失效,接下来再点任何按钮都没有效果了 这样行不通,

ie8下 全选功能报错-ie8下 JS全选功能报错 求达人帮忙看下代码

问题描述 ie8下 JS全选功能报错 求达人帮忙看下代码 // ???? function autoCalDaysNm() { for(var j=1; j<=29; ++j) { var el = $("#writeForm input[name=atdDay" + j + "]"); var d = Date.parse("2016/02/" + el.val()); if (d) { var t = d.toString("

JQuery实现列表中复选框全选反选功能封装(推荐)_jquery

我们在做列表的时候经常会遇到全选,反选进行批量处理问题,例如: 我当时就是简单的实现了,然后想封装到公共的js中,封装的太烂,不好意思贴出来了(就是把实现代码之间放到公共js中,然后每个页面都用固定的id,class,现在想想我都不好意思叫他封装了),然后想到之前老大有写过这个功能去看下他怎么写的,真是没有对比就没有伤害啊,这才叫封装: $(':checkbox[data-check-target]').click(function () { var target = $(this).attr(

总结jQuery checkbox全选/反选代码

在修改Hi GPA的时候需要增加一个全选用户的功能,结果被坑惨了. 首先,最终代码是这么写的:  代码如下 复制代码 var text = $('#select-all-student').html(); if (text == '全选') {     $('input[name="studentNumber"]').prop('checked', true);     $('#select-all-student').html('取消全选') } else {     $('inpu