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


Posted in Javascript onSeptember 08, 2016

因为刚开始接触vue不久,全选的实现参考了知乎上的实现方法:

     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);
};

总结

以上就是这篇文章的全部内容,有不对的地方,还请大家多多指教。希望这篇文章的内容对大家能有所帮助。

Javascript 相关文章推荐
用于自动添加Digg This!按钮的JavaScript
Dec 23 Javascript
jquery 元素相对定位代码
Oct 15 Javascript
基于Jquery的文字自动截取(提供源代码)
Aug 09 Javascript
js操作css属性实现div层展开关闭效果的方法
May 11 Javascript
JavaScript去除数组里重复值的方法
Jul 13 Javascript
Bootstrap框架下下拉框select搜索功能
Mar 26 Javascript
基于chosen插件实现人员选择树搜索自动筛选功能
Sep 24 Javascript
微信小程序 标签传入数据
May 08 Javascript
Vue Router的懒加载路径的解决方法
Jun 21 Javascript
解决vue axios的封装 请求状态的错误提示问题
Sep 25 Javascript
微信小程序实现图片翻转效果的实例代码
Sep 20 Javascript
微信小程序实现转盘抽奖
Sep 21 Javascript
AngularJS 实现JavaScript 动画效果详解
Sep 08 #Javascript
javascript使用 concat 方法对数组进行合并的方法
Sep 08 #Javascript
jQuery插入节点和移动节点用法示例(insertAfter、insertBefore方法)
Sep 08 #Javascript
jQuery删除节点用法示例(remove方法)
Sep 08 #Javascript
jQuery复制节点用法示例(clone方法)
Sep 08 #Javascript
jQuery替换节点用法示例(使用replaceWith方法)
Sep 08 #Javascript
jQuery元素属性操作实例(设置、获取及删除元素属性)
Sep 08 #Javascript
You might like
千呼万唤始出来,DOTA2勇士令状不朽宝藏Ⅱ现已推出
2020/08/25 DOTA
PHP的面试题集
2006/11/19 PHP
非常不错的MySQL优化的8条经验
2008/03/24 PHP
如何取得中文字符串中出现次数最多的子串
2013/08/08 PHP
9个实用的PHP代码片段分享
2015/01/22 PHP
php实现通用的信用卡验证类
2015/03/24 PHP
php二维码生成
2015/10/19 PHP
PHP中set_include_path()函数相关用法分析
2016/07/18 PHP
解决Extjs上传图片无法预览的解决方法
2012/03/22 Javascript
js简单实现删除记录时的提示效果
2013/12/05 Javascript
jQuery随机密码生成的方法
2015/03/09 Javascript
Javascript实现鼠标右键特色菜单
2015/08/04 Javascript
Angularjs注入拦截器实现Loading效果
2015/12/28 Javascript
angular双向绑定模拟探索
2016/12/26 Javascript
javascript+html5+css3自定义提示窗口
2017/06/21 Javascript
使用nodejs+express实现简单的文件上传功能
2017/12/27 NodeJs
vue 内置过滤器的使用总结(附加自定义过滤器)
2018/12/11 Javascript
微信小程序实现订单倒计时
2020/11/01 Javascript
JavaScript使用表单元素验证表单的示例代码
2019/08/20 Javascript
在node环境下parse Smarty模板的使用示例代码
2019/11/15 Javascript
[52:03]Secret vs VG 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/20 DOTA
Nginx搭建HTTPS服务器和强制使用HTTPS访问的方法
2015/08/16 Python
Python实现SMTP发送邮件详细教程
2021/03/02 Python
Python字符编码与函数的基本使用方法
2017/09/30 Python
Python实现监控键盘鼠标操作示例【基于pyHook与pythoncom模块】
2018/09/04 Python
在python 中实现运行多条shell命令
2019/01/07 Python
python实现微信自动回复机器人功能
2019/07/11 Python
python redis连接 有序集合去重的代码
2019/08/04 Python
详解python 降级到3.6终极解决方案
2020/02/06 Python
Python super()方法原理详解
2020/03/31 Python
Pytorch使用PIL和Numpy将单张图片转为Pytorch张量方式
2020/05/25 Python
python给视频添加背景音乐并改变音量的具体方法
2020/07/19 Python
英国健身专家:WIT Fitness
2021/02/09 全球购物
2014年重阳节老干部座谈会局领导发言稿
2014/09/25 职场文书
SpringBoot+Redis实现布隆过滤器的示例代码
2022/03/17 Java/Android
Django + Taro 前后端分离项目实现企业微信登录功能
2022/04/07 Python