>

js仿Metronic高等表格,完毕全选全不选的示范代码

- 编辑:www.bifa688.com -

js仿Metronic高等表格,完毕全选全不选的示范代码

最近做的一个项目需要用到Vue实现全选功能,参考了一下网上的做法,发现用属性计算的复用性不高,于是选用自定义指令,但网上的做法大多是会对原始数据有一定的格式要求,而且没有返回结果,于是做了改进。

全选功能可以说是前端开发中非常常见的一个功能,以前的项目开发用jQuery开发比较多。最近在使用vue前端框架重构之前的项目。从jQuery到vue的转变主要是一个思想想的转变,是将原有的直接操作dom的思想转变到操作数据,用数据驱动dom,也是vue框架的一个核心思想,思想转变过来,对功能的实现自然容易理解一些。

上篇使用Vue.js制作仿Metronic高级表格(一)静态设计介绍了需求、原型设计以及静态页面实现,这篇讲解如何使用Vue渲染数据,实现动态展示。

上代码:

例如下面这个简单的demo

表格数据

<!DOCTYPE html>
<html>
 <head>
  <meta charset="UTF-8">
  <title></title>
 </head>
 <body>
  <div id="app">
  <input type="checkbox" v-model="allCheck" v-check-all="allCheck" check-data="list" result="customerResult" key="demo"> 全选
  <ul> 
   <li v-for="item in list"> 
    <input type="checkbox" v-model="item.checked"> 
    {{item.demo}}
   </li> 
  </ul> 
  <div >
   customerResult: {{customerResult}}
  </div>
  </div>
  <script src="vue.js"></script>
  <script>
   var vm = new Vue({
    el: "#app",
    data:function(){
     return {
      list:[{demo:1},
      {demo:2},
      {demo:3}],
      allCheck:'',
      customerResult:'',
     }
    },
    directives: {
     'check-all': {
      twoWay: true,
      params: ['checkData','result','key'],
      bind() {
       /*为原始数据的每一个对象添加一个checked属性*/
       this.vm[this.params.checkData].forEach((item)=>{
        Vue.set(item,'checked',false)
       });
       /*提取被选中的项*/
       this.setValue=function(){
        let result=[]
        this.vm[this.params.checkData].forEach((item) => {
         if(item.checked){
          result.push(item[this.params.key])
         }
        });
        this.vm[this.params.result]=result
       }
        /*如果所有的列表的checked属性都为true,则选中全选框,否则不选中全选框 */
       this.vm.$watch(this.params.checkData, (data) => {
        if(data.every((item) => item.checked)) {
         this.set(true);
        } else {
         this.set(false);
        }
        this.setValue()
       }, {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;
        });
       }
       this.setValue()
      },
     },
    }
   })
  </script>
 </body>
</html>

图片 1

先定义一个数组来保存所有数据:

通常我们都要获取原始数据中的某个键值,可在“key”中填进想要获取的键值,“result”就是被选中的项了。
有时,我们需要返回一个完整的对象修改一下代码,当不输入key时,返回一个完整的对象数组

按照jQuery的思想来做的话,要选中全选checkbox和所有的checkbox项,分别注册选中事件,判断选中状态来给相关的checkbox设置对应的状态,这就涉及到很多的dom操作。

var vm = new Vue({ 
 el:'#content', 
 data: { 
  book_list: [ 
   {id:1, name:"标准日本语", type: "文化", price:19.00, time: 1492502043}, 
   {id:2, name:"微观经济学", type: "经济", price:29.00, time: 1492502143}, 
   {id:3, name:"大数据时代", type: "经济", price:39.00, time: 1492502243}, 
   {id:4, name:"TCP/IP协议详解", type: "科技", price:49.00, time: 1492502343}, 
   {id:5, name:"大学英语", type: "文化", price:59.00, time: 1492502443}, 
  ] 
 } 
}); 
this.setValue=()=>{
 let result=[]
 this.vm[this.params.checkData].forEach((item) => {
  //删除checked属性
  let temp={};
  (()=>delete Object.assign(temp,item).checked)();
  item.checked?result.push(item[this.params.key]||temp):"";
 });
 this.vm[this.params.result]=result
}

下面就看一下vue数据驱动dom的思想来实现这一功能。

使用v-for指令来渲染,将tr标签改写成:

但时,这时,返回来的数组中对象中并没有与与原数据是相同的引用地址,当需要使用array.$remove()函数时就会失败,新增一个relative参数,用户自定义判断返回的数据是否与原始数据关联

vue数据驱动dom实现功能

<tr v-for="(book, key) in book_list"> 
 <td v-text="key   1"></td> 
 <td v-text="book.name"></td> 
 <td v-text="book.type"></td> 
 <td v-text="book.price"></td> 
 <td v-text="book.time"></td> 
 <td> 
  <button class="btn btn-info btn-xs"> 
   <i class="fa fa-pencil"></i> 
   修改 
  </button> 
  <button class="btn btn-danger btn-xs"> 
   <i class="fa fa-trash"></i> 
   删除 
  </button> 
 </td> 
</tr> 
this.setValue = () => {
 let result = []
 this.vm[this.params.checkData].forEach((item) => {
  if(this.params.relative) {
   item.checked ? result.push(item) : "";
  }else{
   //删除checked属性
   let temp = {};
   (() => delete Object.assign(temp, item).checked)();
   item.checked ? result.push(item[this.params.key] || temp) : "";
  }
 });
 this.vm[this.params.result] = result
}
<div class="checkbox">
  <label for="quan">
    <!-- 这里的 $event 是将当前对象传入进去,具体详情请参照vue官方文档 -->
    <input id="quan" type="checkbox" @click="checkAll($event)"> 全选
  </label>
  <label>
    <!-- v-model 双向数据绑定命令 -->
    <input class="checkItem" type="checkbox" value="apple" v-model="checkData"> apple
  </label>
  <label>
    <input class="checkItem" type="checkbox" value="banana" v-model="checkData"> banana
  </label>
  <label>
    <input class="checkItem" type="checkbox" value="orange" v-model="checkData"> orange
  </label>
</div>
<script>
  new Vue({
    el: '#app',
    data(){
      return {
        checkData: [] // 双向绑定checkbox数据数组
      }
    },
    watch: { // 监视双向绑定的数据数组
      checkData: {
        handler(){ // 数据数组有变化将触发此函数
          if(this.checkData.length == 3){
            document.querySelector('#quan').checked = true;
          }else {
            document.querySelector('#quan').checked = false;
          }
        },
        deep: true // 深度监视
      }
    },
    methods: {
      checkAll(e){ // 点击全选事件函数
        var checkObj = document.querySelectorAll('.checkItem'); // 获取所有checkbox项
        if(e.target.checked){ // 判定全选checkbox的勾选状态
          for(var i=0;i<checkObj.length;i  ){
            if(!checkObj[i].checked){ // 将未勾选的checkbox选项push到绑定数组中
              this.checkData.push(checkObj[i].value);
            }
          }
        }else { // 如果是去掉全选则清空checkbox选项绑定数组
          this.checkData = [];
        }
      }
    }
  });
</script>

图片 2

当数据长度大于2个时,需要判断2N次,相当消耗性能,优化一下:

利用vue的双向数据绑定v-model命令,当勾选时,checkbox的value值会自动push到所绑定的数组checkData中去,省去了不少对dom的操作。

其指令含义为:遍历book_list对象,将元素赋值给book,索引赋值给key,并且使用元素渲染该tr标签
值得注意的是:
① 应该使用v-text来设置文本值,这样不会出现闪烁问题。
② Vue2.0中,不支持隐式的$index,需要显式声明,例如上述代码中"(book, key) in book_list",key可以看做$index
数据渲染完了,但是看效果会知道,价格、更新时间需要做一些格式调整。
Vue1.0中对于价格的调整可以使用

'check-all', {
  twoWay: true,
  params: ['checkData', 'result', 'key','relative'],
  /*checkData:列表数据,
  result:返回的结果,
  key:列表数据中需要返回的字段,
  relative:是否返回与列表数据相同引用地址的选中结果*/
  bind() {
   /*提取被选中的项*/
  this.setValue = () => {
   let result = []
   if (this.params.relative) {
    this.vm[this.params.checkData].forEach((item) => {
     item.checked ? result.push(item) : "";
    });
   } else {
    this.vm[this.params.checkData].forEach((item) => {
     //删除checked属性
     let temp = {};
     (() => delete Object.assign(temp, item).checked)();
     item.checked ? result.push(item[this.params.key] || temp) : "";
    });
   }
   this.vm[this.params.result] = result
  };
   /*为原始数据的每一个对象添加一个checked属性*/
  this.addChecked = () => {
   this.vm[this.params.checkData].forEach((item) => {
    Vue.set(item, 'checked', false)
   });
  };
  /*如果所有的列表的checked属性都为true,则选中全选框,否则不选中全选框 */
  this.vm.$watch(this.params.checkData, (data) => {
   if(!data.length) return;
   data.every((item) => item.checked) ? this.set(true) : this.set(false);
   this.setValue()
  }, {deep: true});
  //当列表发生变化时重新绑定
  this.vm.$watch(this.params.checkData, (data) => {
   if(!data.length) return
   this.addChecked();
  });
  },
  // checkAll发生更改时 
  update(checkAll) {
   /*如果全选框被选中,则将列表的所有checked属性转为true,否则转为false */
   checkAll ? this.vm[this.params.checkData].forEach((item) => {
    item.checked = true
   }) : this.vm[this.params.checkData].forEach((item) => {
    item.checked = false
   });
   this.setValue()
  },
 }

如果是固定选项这样是可以实现的,但是这种方法有一些弊端,双向绑定数组数据是写死的,不太灵活,如果增加了checkbox选项,要更改wach里绑定数组的长度判断。

{{book.price | currency}} 

这时只需要判断N 1次。

有时候checkbox选项也是后台动态获取过来的,这样也灵活一些。

也就是过滤器,但在Vue2.0中,已废弃默认过滤器了,这意味着我们需要自定义过滤器,并且注册到Vue对象中去。
不难写出currencydate过滤器为:

以上这篇Vue自定义指令实现checkbox全选功能的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。

例如后台数据是这样的:

Vue.filter('date', function (timestamp) { 
 let date = new Date(timestamp*1000); 
 let y = date.getFullYear(); 
 let month = date.getMonth() 1; 
 let d = date.getDate(); 
 let h = date.getHours(); 
 let m = date.getMinutes(); 
 let s = date.getSeconds(); 
 return y   '年'  
   (month < 10 ? '0':'')   month   '月'   
   (d < 10 ? '0':'')   d   '日'   
   (h < 10 ? '0':'')   h   ':'   
   (m < 10 ? '0':'')   m   ':'   
   (s < 10 ? '0':'')   s; 
}); 
Vue.filter('currency', function(money, unit, fixed){ 
 if (isNaN(money)) {return "";} 
 if (typeof fixed == 'undefined' || isNaN(fixed)) { 
  fixed = 2 
 } 
 if (typeof unit =='undefined') { 
  unit = '¥ '; 
 } 
 let num = parseFloat(money); 
 return unit   num.toFixed(fixed); 
}); 

您可能感兴趣的文章:

  • 利用Vue.js指令实现全选功能
  • 使用vue.js实现checkbox的全选和多个的删除功能
  • vue实现全选和反选功能
  • vue.js内部自定义指令与全局自定义指令的实现详解(利用directive)
  • Vue自定义指令使用方法详解
  • Vue自定义指令详解
  ajaxData: [{
    name: 'a',
    value: 'apple'
  },{
    name: 'b',
    value: 'banana'
  },{
    name: 'c',
    value: 'orange'
  }]

再次修改tr模板为:

需要先动态渲染checkbox选项,在进行数据绑定。

<td>{{book.price | currency}}</td> 
<td>{{book.time | date}}</td> 
<div id="app">
  <div class="checkbox">
    <label for="quan">
      <!-- 这里的 $event 是将当前对象传入进去,具体详情请参照vue官方文档 -->
      <input id="quan" type="checkbox" @click="checkAll($event)"> 全选
    </label>
    <label v-for="item in ajaxData">
      <!-- v-model 双向数据绑定命令 -->
      <input class="checkItem" type="checkbox" :value="item.value" v-model="checkData"> {{item.name}}
    </label>
  </div>
</div>
<script>
  new Vue({
    el: '#app',
    data(){
      return {
        ajaxData: [{ // 后台请求过来的数据
          name: '选项1',
          value: 'apple'
        },{
          name: '选项2',
          value: 'banana'
        },{
          name: '选项3',
          value: 'orange'
        }],
        checkData: [] // 双向数据绑定的数组
      }
    },
    watch: {
      checkData: { // 监视双向绑定的数组变化
        handler(){
          if(this.checkData.length == this.ajaxData.length){
            document.querySelector('#quan').checked = true;
          }else {
            document.querySelector('#quan').checked = false;
          }
        },
        deep: true
      }
    },
    methods: {
      checkAll(e){ // 点击全选事件
        if(e.target.checked){
          this.ajaxData.forEach((el,i)=>{
            // 数组里没有这一个value才push,防止重复push
            if(this.checkData.indexOf(el.value) == '-1'){ 
              this.checkData.push(el.value);
            }
          });
        }else { // 全不选选则清空绑定的数组
          this.checkData = [];
        }
      }
    }
  });
</script>

值得注意的是:过滤器不能和v-text指令配合使用,下述代码无法生效:

图片 3

<td v-text="book.price | currency"></td> 
<td v-text="book.time | date"></td> 

方法并不是最优的写法,也存在一些弊端,欢迎各位指点迷津,一起探讨。

修改后的表格效果如下:

github地址:

图片 4

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

分页展示

您可能感兴趣的文章:

  • Vue自定义指令实现checkbox全选功能的方法
  • vue 全选与反选的实现方法(无Bug 新手看过来)
  • vue checkbox 全选 数据的绑定及获取和计算方法
  • vue2.0在table中实现全选和反选的示例代码
  • vue实现全选和反选功能
  • vue2.0中vue-cli实现全选、单选计算总价格的实例代码
  • vue实现全选、反选功能
  • 使用vue.js实现checkbox的全选和多个的删除功能
  • 利用Vue.js实现checkbox的全选反选效果
  • 利用Vue.js指令实现全选功能

分页其实就是只显示原始数据中,索引值在某一个范围内的数据,可以理解为是一种数据的过滤处理.
如果知道了页容量,当前页码,原始数据集,就能计算出当前页要显示哪些数据。
页码从1开始,那么第N页的数据,他的索引(从0开始)范围应该是:(N - 1)*SIZE ~ N*SIZE - 1
由于"分页"这一动作具有普遍性,我们现在methods中定义一个pageData方法:

methods: { 
 pageData: function (data, page_size, page_num) { 
  if (!(data instanceof Array)) {return [];} 
  let start = (page_num - 1)*page_size; 
  return data.slice(start, start   page_size); 
 } 
} 

值得注意的是:slice方法返回的是数组的原始元素,而不是数组的备份(copy)。
"当前页的数据" 我们使用计算属性来完成,而不是方法:

computed : { 
 page_book_list: function() { 
  return this.pageData(this.book_list, this.page_size, this.page_num); 
 } 
} 

值得注意的是:这里没什么值得好注意的。page_size、page_num是在data中定义的。
此时表格的数据集就得换成page_book_list了
<tr v-for="(book, key) in page_book_list"> 

页码

要渲染页码列表,必须先得到总页数,因为后期可能会增加关键字过滤,所以我们使用计算属性来得到总页数:
不足一页也要当一页来显示

computed : { 
 total_page: function () { 
  let len = this.book_list.length; 
  let ret = parseInt(len/this.page_size); 
  if ((len % this.page_size) != 0) { 
   ret  ; 
  } 
  return ret < 1 ? 1 : ret;; 
 } 
} 

页码列表的渲染使用v-for即可,参照bootstrap的页码html,不难写出:

<ul class="pagination"> 
 <li :class="{disabled:page_num<=1}" @click="prePage()"> 
  <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" ><i>«</i></a></li> 
 <li v-for="n in total_page" :class="{active:page_num==n}"> 
  <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" v-text="n" @click="page_num=n"></a></li> 
 <li :class="{disabled:page_num >= total_page}" @click="nextPage()"> 
  <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" ><i>»</i></a> 
 </li> 
</ul> 

值得注意的是:

@click是绑定click事件,可以是函数执行,也可是是js代码执行
:class是绑定class属性,格式是"样式名称: 条件",当条件为true时,才设置这个样式。
此处为何不用v-show?因为效果太难看了

自定义页容量

这就很简单了,将页码下拉框改造一下即可,不难写出:

<select class="form-control" v-model="page_size"> 
 <option 
  v-for = "size in [5,10,15,20]" 
  :value = "size" 
  v-text = "size '条'"> 
 </option> 
</select> 

:value是绑定value的值
v-model会使得select的value与page_size绑定,这个绑定双向的

这里会出现一个小bug,即在切换页容量的时候,会导致总页数变化,有可能总页数会小于当前页。
于是在获取总页数的时候需要对当前页做一些变动:

total_page: function () { 
 let len = this.book_list.length; 
 let ret = parseInt(len/this.page_size); 
 if ((len % this.page_size) != 0) { 
  ret  ; 
 } 
 if (this.page_num > ret) { 
  this.page_num = ret; 
 } else if (this.page_num < 1) { 
  this.page_num = 1; 
 } 
 return ret < 1 ? 1 : ret;; 
} 

本次效果图:

图片 5

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

您可能感兴趣的文章:

  • vue.js实现条件渲染的实例代码
  • Vue.js学习教程之列表渲染详解
  • 用v-html解决Vue.js渲染中html标签不被解析的问题
  • 学习vue.js条件渲染
  • Vue.JS入门教程之列表渲染
  • Vue.js实现多条件筛选、搜索、排序及分页的表格功能
  • vue.js声明式渲染和条件与循环基础知识

本文由必发88官网发布,转载请注明来源:js仿Metronic高等表格,完毕全选全不选的示范代码