使用Vue.js怎么实现一个可排序的表格组件
这期内容当中小编将会给大家带来有关使用Vue.js怎么实现一个可排序的表格组件,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。
html:
<divid="app"v-cloak> <v-table:data="data":columns="columns"></v-table> <button@click="add">新增</button> </div>
把父组件中定义的 data 与 columns 传入 v-table 组件。
js:
Vue.component('vTable',{ props:{ //表头列名称 columns:{ type:Array, default:function(){ return[]; } }, //数据 data:{ type:Array, default:function(){ return[]; } } }, //为了不影响原始数据,这里定义了相应的需要操作的数据对象 data:function(){ return{ currentColumns:[], currentData:[] } }, //render实现方式 render:function(createElement){ varthat=this; /** *创建列样式与表头 */ varths=[];//<th>标签数组 varcols=[];//<cols>标签数组 this.currentColumns.forEach(function(col,index){ if(col.width){//创建列样式 cols.push(createElement('col',{ style:{ width:col.width } })) } if(col.sortable){ ths.push(createElement('th',[ createElement('span',col.title), //升序 createElement('a',{ class:{ on:col.sortType==='asc' }, on:{ click:function(){ that.sortByAsc(index) } } },'↑'), //降序 createElement('a',{ class:{ on:col.sortType==='desc' }, on:{ click:function(){ that.sortByDesc(index); } } },'↓') ])); }else{ ths.push(createElement('th',col.title)); } }); /** *创建内容 */ vartrs=[];//<tr>标签数组 this.currentData.forEach(function(row){//遍历行 vartds=[];//<td>标签数组 that.currentColumns.forEach(function(cell){//遍历单元格 tds.push(createElement('td',row[cell.key])); }); trs.push(createElement('tr',tds)); }); returncreateElement('table',[ createElement('colgroup',cols), createElement('thead',[ createElement('tr',ths) ]), createElement('tbody',trs) ]) }, methods:{ //初始化表头 initColumns:function(){ this.currentColumns=this.columns.map(function(col,index){ //新建字段,标识当前列排序类型;默认为“不排序” col.sortType='normal'; //新建字段,标识当前列在数组中的索引 col.index=index; returncol; }); }, //初始化数据 initData:function(){ this.currentData=this.data.map(function(row,index){ //新建字段,标识当前行在数组中的索引 row.index=index; returnrow; }); }, //排序 order:function(index,type){ this.currentColumns.forEach(function(col){ col.sortType='normal'; }); //设置排序类型 this.currentColumns[index].sortType=type; //设置排序函数 varsortFunction; varkey=this.currentColumns[index].key; switch(type){ default://默认为asc排序 case'asc': sortFunction=function(a,b){ returna[key]>b[key]?1:-1; }; break; case'desc': sortFunction=function(a,b){ returna[key]<b[key]?1:-1; }; break; } this.currentData.sort(sortFunction); }, //升序 sortByAsc:function(index){ this.order(index,'asc'); }, //降序 sortByDesc:function(index){ this.order(index,'desc'); } }, watch:{ data:function(){ this.initData(); //找出排序字段 varsortedColumn=this.currentColumns.filter(function(col){ returncol.sortType!=='normal'; }); if(sortedColumn.length>0){ if(sortedColumn[0].sortType==='asc'){ this.sortByAsc(sortedColumn[0].index); }else{ this.sortByDesc(sortedColumn[0].index); } } } }, mounted(){ this.initColumns(); this.initData(); } }); varapp=newVue({ el:'#app', data:{ //title、key与width必填;sortable选填 columns:[ { title:'名称', key:'name', width:'60%' }, { title:'数量', key:'num', width:'20%', sortable:true }, { title:'单价', key:'unitPrice', width:'20%', sortable:true } ], data:[ { name:'真果粒牛奶饮品', num:2, unitPrice:59.9 }, { name:'苏泊尔(SUPOR)电压力锅', num:1, unitPrice:378.0 }, { name:'乐事(Lay\'s)薯片', num:3, unitPrice:63.0 } ] }, methods:{ add:function(){ this.data.push({ name:'良品铺子休闲零食大礼包', num:5, unitPrice:59.80 }); } } });
为了让排序后的 columns 与 data 不影响原始数据,我们在组件的 data 中定义了相应的当前数据对象。因此在 method 中使用传入的值,初始化这些数据对象,最后在 mounted() 调用这些初始化方法。
columns 中的每一项都是包含 title(列名)、key(对应 data 中的字段名)、width(宽度) 以及 sortable(是否可排序) 的对象。其中,只有 sortable 为可选项,如果设定为 true,则表示该列可点击排序。
map() 会对数组的每一项运行给定函数,返回每次函数调用的结果组成的数组。
排序分为升序与降序,因为只能对某一列进行排序,所以是互斥操作。我们为每一列新增一个 sortType ,用于标识该列的排序类型,初始值为 normal,表示不排序。
因为排序字段可能是任意列,所以我们为每一列新增一个 index,用于标识当前列在数组中的索引。
在 Render 函数中,首先创建列样式与表头,接着创建内容。
Render 函数中的 createElement 可以简写为 h,这样代码会变得更简洁:
render:function(h){ varthat=this; /** *创建列样式与表头 */ varths=[];//<th>标签数组 varcols=[];//<cols>标签数组 this.currentColumns.forEach(function(col,index){ if(col.width){//创建列样式 cols.push(h('col',{ style:{ width:col.width } })) } if(col.sortable){ ths.push(h('th',[ h('span',col.title), //升序 h('a',{ class:{ on:col.sortType==='asc' }, on:{ click:function(){ that.sortByAsc(index) } } },'↑'), //降序 h('a',{ class:{ on:col.sortType==='desc' }, on:{ click:function(){ that.sortByDesc(index); } } },'↓') ])); }else{ ths.push(h('th',col.title)); } }); /** *创建内容 */ vartrs=[];//<tr>标签数组 this.currentData.forEach(function(row){//遍历行 vartds=[];//<td>标签数组 that.currentColumns.forEach(function(cell){//遍历单元格 tds.push(h('td',row[cell.key])); }); trs.push(h('tr',tds)); }); returnh('table',[ h('colgroup',cols), h('thead',[ h('tr',ths) ]), h('tbody',trs) ]) }
创建内容时,我们首先遍历所有行,然后在循环内部遍历所有列,得出 <td> 与 <tr> 内容。
创建表头时,对是否排序做了相应的处理,并绑定了相应的点击事件。
点击事件定义在 methods 中,因为升序与降序逻辑大体相同,所以又封装了一层 order() 排序函数。
order() 排序函数内部使用了数组的 sort() 方法。sort() 方法会调用每个数组项的 toString() 方法,然后比较得到的字符串,即使数组中的每一项是数值,比较的也是字符串。这里传入了一个比较函数作为参数。为了兼容所有浏览器,在比较函数中,我们返回的是 1 或者 -1。
排序之前,先把所有列的排序类型都设置为不排序,然后再更新当前列的排序状态。这就会对应到 render 函数里绑定 <a> 标签的 class 中的 on 样式,即当前列排序状态会被高亮显示。
表格被初始化渲染之后,如果 data 发生变化,那么表格组件数据应该也要同步更新。因此,我们在 watch 中做了数据更新以及数据重排操作。
css:
[v-cloak]{ display:none; } table{ width:100%; margin-bottom:24px; /*合并边框模型*/ border-collapse:collapse; border-spacing:0; /*在空单元格周围绘制边框*/ empty-cells:show; border:1pxsolid#e9e9e9; } tableth{ font:bold14px"TrebuchetMS",Verdana,Arial,Helvetica,sans-serif; background:#CAE8EA; color:#5c6b77; /*设置文本粗细*/ font-weight:600; /*段落中的文本不进行换行*/ white-space:nowrap; border-top:1pxsolid#C1DAD7; } tabletd,tableth{ padding:8px16px; text-align:left; border-right:1pxsolid#C1DAD7; border-bottom:1pxsolid#C1DAD7; } tabletha{ /*不独占一行的块级元素*/ display:inline-block; margin:04px; cursor:pointer; } tabletha.on{ color:#3399ff; } tabletha:hover{ color:#3399ff; }
上述就是小编为大家分享的使用Vue.js怎么实现一个可排序的表格组件了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注恰卡编程网行业资讯频道。
推荐阅读
-
Vue.js组件是什么
-
Vue.js响应式数据如何实现
-
怎么将Vue.js应用程序与Drupal做一个集成
怎么将Vue.js应用程序与Drupal做一个集成本文小编为大家详...
-
Vue.js双向绑定的方法是什么
Vue.js双向绑定的方法是什么本篇内容主要讲解“Vue.js双向...
-
vue.js怎么下载安装
vue.js怎么下载安装本文小编为大家详细介绍“vue.js怎么下...
-
Vue.js组件化怎么实现
Vue.js组件化怎么实现本文小编为大家详细介绍“Vue.js组件...
-
vue.js跨域问题如何解决
vue.js跨域问题如何解决本文小编为大家详细介绍“vue.js跨...
-
Vue3中怎么用WeakMap作为缓存区
-
如何使用Vue.js和MJML创建响应式电子邮件
-
怎么在Vue.js中引入图片路径
今天就跟大家聊聊有关怎么在Vue.js中引入图片路径,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家...