最近用vue做了两个项目,都需要实现全选和反选的功能。这两个项目使用了两种实现方法。第一个项目使用vue的computed,第一个项目使用vue的computed。这两个项目都是用指令实现的,我觉得指令用起来更方便。第一次全选是在刚接触vue的时候。全选的实现参考知乎上的实现方法(链接:https://www.zhihu.com/question/37833194/answer/91812053):1.从服务器获取数据,为每一个设置checked属性物品。2.计算选择数量selectCount。如果选中的数量等于selectItems的数量,则全选selectAll。checked属性设置为true,反选时设置为false。4、每次selectItems的属性发生变化时,将被选中的项放入数组checkedGroups中。下面是实现代码://selectalldata:function(){return{selectItems:[],//从服务器获取的数据}},computed:{//所有选择selectAll绑定到checkbox的模型:{get:function(){returnthis.selectCount==this.selectItems.length;},set:function(value){this.selectItems.forEach(function(item){item.checked=value;});returnvalue;}},//选择数量selectCount:{get:function(){vari=0;this.selectItems.forEach(function(item){if(item.checked){i++;}});returni;}},//选中数组checkedGroups:{get:function(){varcheckedGroups=[];this.selectItems.forEach(function(item){if(item.checked){checkedGroups.push(item);}});returncheckedGroups;}}}这个方法用起来不是很方便,首先是难以复用,每次要用都要写computed,其次selectAll,checkedGroups,selectItems是固定的,不太灵活。所以在这个项目中,我使用vue指令重新实现了全选的功能。directive的思想其实和computed差不多。首先添加代码:exportdefault{'check-all':{twoWay:true,params:['checkData'],bind(){/**-如果所有列表的checked属性为true,则选中所有复选框,否则不要选中所有复选框*/this.vm.$watch(this.params.checkData,(checkData)=>{if(checkData.every((item)=>item.checked)){this.set(true);}else{this.set(false);}},{deep:true});},//checkAll变化时update(checkAll){/**-如果全选框被选中,则将所有选中的属性的列表为真,否则转向假*/if(checkAll){this.vm[this.params.checkData].forEach((item)=>{item.checked=true;});}else{this.vm[this.params.checkData].forEach((item)=>{item.checked=false;});}},},};调用:
先说一下使用这种方式的好处:1、使用方便。需要用到的地方只要写v-check-all命令和check-data即可。2、所有选中的模型和数组的名称都可以自定义,可以使用任意名称。全选的模型不想调用checkAll可以调用checkAllData,数组不想调用checkData调用dataFromServer也可以在命令中指定为twoWay为true,可以使用this.set(value)设置checkAll的值,使用params来接收绑定命令元素上的属性值checkData,这是要操作的数组。使用this.vm获取命令上下文,调用上下文的$watch监听checkData的变化,如果checkData全部被选中,则设置checkAll为true,否则设置checkAll为false。当指令值(checkAll)发生变化时,如果为真,则将checkData的checked属性设置为真,否则为假。至此,一个全选命令就完成了。在做这个selectall命令的时候,本来想用paramWatchers来监听checkData的变化,但是发现checkData变化的时候,并不会触发paramWatchers的回调。查看源码后发现paramWatchers其实调用了$watch。但不支持深度检测:Directive.prototype._setupParamWatcher=function(key,expression){varself=this;varcalled=false;varunwatch=(this._scope||this.vm).$watch(expression,function(val,oldVal){self.params[key]=val;//sinceweareinimmediatemode,//onlycalltheparamchangecallbacksifthisisnotthefirstupdate.if(called){varcb=self.paramWatchers&&self.paramWatchers[key];if(cb){cb.call(self,val,oldVal);}}else{called=true;}},{immediate:true,user:false});(this._paramUnwatchFns||(this._paramUnwatchFns=[])).push(unwatch);};入行一年多了,还有很多东西要学。如果有什么不对的地方,请给我你的建议。为了鼓励自己多总结,我开通了微信公众号公众号(前端文章)。最近一直在用Vue做项目,近期应该会写一些关于Vue的文章。有兴趣的可以关注一下,也可以投稿,多交流。
