用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中

下面为实现代码:

    //全选
    data: function() {
        return {
            selectItems: [],  // 从服务器拿到的数据
        }
    },
    computed: {
        // 全选checkbox绑定的model
        selectAll: {
            get: function() {
                return this.selectCount == this.selectItems.length;
            },
            set: function(value) {
                this.selectItems.forEach(function(item) {
                    item.checked = value;
                });
                return value;
            }
        },
        //选中的数量
        selectCount: {
            get: function() {
                var i = 0;
                this.selectItems.forEach(function(item) {
                    if (item.checked) {
                        i++;
                    }
                });
                return i;
            }
        },
        //选中的数组
        checkedGroups: {
            get: function() {
                var checkedGroups = [];
                this.selectItems.forEach(function(item) {
                    if (item.checked) {
                        checkedGroups.push(item);
                    }
                });
                return checkedGroups;
            }
        }
    }

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

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

export default {
    ‘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) {
            /**
             - 如果全选框被选中,则将列表的所有checked属性转为true,否则转为false
             */
            if (checkAll) {
                this.vm[this.params.checkData].forEach((item) => {
                    item.checked = true;
                });
            } else {
                this.vm[this.params.checkData].forEach((item) => {
                    item.checked = false;
                });
            }
        },
    },
};

调用:
<input type="checkbox" v-model="checkAll" v-check-all="checkAll" check-data="checkData">
<ul>
<li v-for="item in checkData">
<input type="checkbox" v-model="item.checked">
{{item.text}}
</li>
</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,但是不支持深度检测:

Directive.prototype._setupParamWatcher = function (key, expression) {
  var self = this;
  var called = false;
  var unwatch = (this._scope || this.vm).$watch(expression, function (val, oldVal) {
    self.params[key] = val;
    // since we are in immediate mode,
    // only call the param change callbacks if this is not the first update.
    if (called) {
      var cb = 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);
};

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

时间: 2024-10-06 16:36:23

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

vue基础之全选,不选

先上效果 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible"

vue中实现全选功能

<!DOCTYPE html><html><head><meta charset="utf-8"><title>Vue 测试实例 - 菜鸟教程(runoob.com)</title><script src="https://cdn.bootcss.com/vue/2.2.2/vue.min.js"></script></head><body>  

vue 中的 全选和 反选

<template> <div> <input type='checkbox' class='input-checkbox' v-model='checked' v-on:click='checkedAll'>全选 <template v-for='checkb in checkboxData'> <input type='checkbox' name='checkboxinput' class='input-checkbox' v-model='ch

一个全选按钮js的案例

<html><head><script type="text/javascript">        // 全选按钮选中标志      var checkflag = "false";      // 全选功能      function selectAll(name){          var field = document.getElementsByName(name);          // 如果全选按钮状态是未选中 

关于input[type=&#39;checkbox&#39;]全选的问题

今天在做一个全选功能的时候,发现了一个问题,就是如果我在选择全选之前,我就已经选择了一个input,然后我再去选择全选并且以后再取消全选的时候,这个我之前选择的input始终处于选择状态,但是他的checked的值一直是在true和false之间变化,当checked=false的时候,仍然是被选中的.到现在还没处理好这个问题.希望看到的哪位大神能给个好的解决办法,实在感激.下面是类似的代码. <!DOCTYPE html><html lang="en"><

checkbox做全选按钮

1.先写一个html页面,里面写一个全选按钮和几个复选框,实现下面2个要求 (1)点击全选按钮选中时,所有的复选框选中. (2)点击全选按钮取消选中时,所有复选框取消选中. <input type="checkbox" id="quanxuan" />全选<br /> <input type="checkbox" class="qx" />aa<br /> <input t

如何实现复选框的全选和取消全选效果

如何实现复选框的全选和取消全选效果:在很多网站都有这样的功能,当点击一个全选按钮之后,所有的复选框都会被选中,再点击之后会取消全选,功能非常的人性化,可以省却很多人力,下面就简单介绍一下JS如何实现此功能,代码实例如下: <!DOCTYPE html> <html> <head> <meta charset=" utf-8"> <meta name="author" content="http://ww

Axure 7.0实现复选框全选和取消全选

使用Axure原型工具对产品进行设计,使用复选框来实现全选中和全取消效果,也可以利用按钮或文字做为开关来控制效果,下面主要介绍使用复选框来实现全选中和全取消效果. 1/1 首先输入复选框效果的文字,并为每个复选框建立名称,方便后期对其辨认,例如:选择你最喜欢居住的城市,建立一个全选的复选框进行全选or取消全选效果 1/2 设置全选中 1/2/1 选择全选复选框,双击(选中状态改变时),打开新增用例对话框 1/2/2  设置用例名称,设置条件判断为真 1/2/3 选择(选中),勾选需要被选中的复选

js 全选选框与取消全选代码

设置一个全选选框和四个子选框,要实现点击全选后四个子选框选中,取消全选后四个子选框也取消.全选后点击某个子选框,全选也能取消.当四个子选框都选中时,全选框也被选择. 实现代码: <script> var a=document.getElementById("a"); var b=document.getElementsByClassName("b"); //全选与取消全选 var y=true; a.onchange=function(){ if(a.c