我们基于 Vue.js 实现一个可根据某列进行排序的表格组件。

一个表格包含表头和数据两部分内容。因此,我们定义两个数组,columns 表示表头信息,在 <thread> 中渲染,并可在此指定某一列是否需要排序;data 表示数据。

html:

<div id="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) {var that = this;/*** 创建列样式与表头*/var ths = [];//<th> 标签数组var cols = [];//<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));}});/*** 创建内容*/var trs = [];//<tr> 标签数组this.currentData.forEach(function (row) {//遍历行var tds = [];//<td> 标签数组that.currentColumns.forEach(function (cell) {//遍历单元格tds.push(createElement('td', row[cell.key]));});trs.push(createElement('tr', tds));});return createElement('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;return col;});},//初始化数据initData: function () {this.currentData = this.data.map(function (row, index) {//新建字段,标识当前行在数组中的索引row.index = index;return row;});},//排序order: function (index, type) {this.currentColumns.forEach(function (col) {col.sortType = 'normal';});//设置排序类型this.currentColumns[index].sortType = type;//设置排序函数var sortFunction;var key = this.currentColumns[index].key;switch (type) {default://默认为 asc 排序case 'asc':sortFunction = function (a, b) {return a[key] > b[key] ? 1 : -1;};break;case 'desc':sortFunction = function (a, b) {return a[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();//找出排序字段var sortedColumn = this.currentColumns.filter(function (col) {return col.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();}
});var app = new Vue({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) {var that = this;/*** 创建列样式与表头*/var ths = [];//<th> 标签数组var cols = [];//<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));}});/*** 创建内容*/var trs = [];//<tr> 标签数组this.currentData.forEach(function (row) {//遍历行var tds = [];//<td> 标签数组that.currentColumns.forEach(function (cell) {//遍历单元格tds.push(h('td', row[cell.key]));});trs.push(h('tr', tds));});return h('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: 1px solid #e9e9e9;
}table th {font: bold 14px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;background: #CAE8EA;color: #5c6b77;/*设置文本粗细*/font-weight: 600;/*段落中的文本不进行换行*/white-space: nowrap;border-top: 1px solid #C1DAD7;
}table td, table th {padding: 8px 16px;text-align: left;border-right: 1px solid #C1DAD7;border-bottom: 1px solid #C1DAD7;
}table th a {/*不独占一行的块级元素*/display: inline-block;margin: 0 4px;cursor: pointer;
}table th a.on {color: #3399ff;
}table th a:hover {color: #3399ff;
}
复制代码

效果:


本文示例代码

说说如何基于 Vue.js 实现表格组件相关推荐

  1. 基于Vue.js的表格分页组件

    转载自 基于Vue.js的表格分页组件 有一段时间没更新文章了,主要是因为自己一直在忙着学习新的东西而忘记分享了,实在惭愧. 这不,大半夜发文更一篇文章,分享一个自己编写的一个Vue的小组件,名叫Bo ...

  2. vue手机端项目php,MintUI基于Vue.js移动端组件库详解

    Mint UI 包含丰富的 CSS 和 JS 组件,能够满足日常的移动端开发需要.接下来通过本文给大家分享Mint UI 基于 Vue.js 移动端组件库,需要的朋友参考下吧,希望能帮助到大家. 官网 ...

  3. vue php 分页组件,基于Vue.js的表格分页组件

    有一段时间没更新文章了,主要是因为自己一直在忙着学习新的东西而忘记分享了,实在惭愧. 这不,大半夜发文更一篇文章,分享一个自己编写的一个Vue的小组件,名叫BootPage.不了解Vue.js的童鞋可 ...

  4. 基于Vue.js活动倒计时组件

    vue2-countdown vue活动倒计时组件及遇到的坑 基于vue2.x的活动倒计时组件 主要是最近为了公司做一个倒计时活动才找到了这个组件使用的.于是去github上翻看了文档结果是一年多没更 ...

  5. 基于Vue.js的iView组件库table组件内render 里面 tab 里面的单选

    先上效果图: 打印选中的结果: 代码如下: <template><div><!-- 列表信息 --> <div class="listfile&qu ...

  6. 基于Vue.js制作的仿车轮驾考通APP端页面

    背景:学习完Vue,老师要求期末作业以Vue技术做一个手机端或者PC端的前端小项目.期末临近,周围的同学有的仿微信APP端,有的仿QQAPP端.小萍去年考科目一用了车轮驾考通刷题,然后她最后决定基于V ...

  7. vue横向树结构_基于vue.js实现树形表格的封装

    基于vue.js实现树形表格的封装(vue-tree-table) 前言由于公司产品(基于vue.js)需要,要实现一个树形表格的功能,百度.google找了一通,并没有发现很靠谱的,也不是很灵活.所 ...

  8. iView 3.3.0 发布,基于 Vue.js 的企业级 UI 组件库

    iView 3.3.0 发布了,代号 Transistor ,iView 是一套基于 Vue.js 的企业级 UI 组件库,主要服务于 PC 界面的中后台产品. 本次更新如下: https://www ...

  9. iView 3.4.0 发布,基于 Vue.js 的企业级 UI 组件库

    百度智能云 云生态狂欢季 热门云产品1折起>>>   iView 3.4.0 发布了,iView 是一套基于 Vue.js 的企业级 UI 组件库,主要服务于 PC 界面的中后台产品 ...

最新文章

  1. 简述Qt编程中遇到的编码格式问题
  2. C++|STL学习笔记-map的属性(大小以及是否存在)
  3. 王道 —— 操作系统的运行机制和体系结构
  4. 计算机图形直线分析,基本图形分析法:等腰三角形(一)
  5. Linux 下源代码阅读工具 —— vim + TagList + CTags
  6. telnet怎么算成功_有机肥发酵剂有的作用,怎么才算发酵成功?
  7. Shell总结(整理)
  8. Atitit 马尔可夫过程(Markov process) hmm隐马尔科夫。 马尔可夫链,的原理attilax总结
  9. python:使用sklearn 计算 precision、recall、F1 score(多分类)
  10. hdu2037-简单dp
  11. 计算机专业朋友圈文案,朋友圈文案合集_用来发微信朋友圈的句子
  12. 2021年茶艺师(中级)考试题库及茶艺师(中级)报名考试
  13. 我常用的轻量化哈希校验工具,右键菜单栏一键计算文件Hash~
  14. html2canvas 截图丢失部分元素的问题
  15. PC微信hook学习笔记(一)—— 获取个人信息
  16. 巧用计算机课件,如何用电脑录制ppt讲解视频?
  17. 打印信息无法连接服务器,打印机无法连接服务器
  18. PrestaShop二次开发-插件|支付|模板|跳转|功能|模块|外贸信用卡-1
  19. 做数据分析的女孩子,职业发展前景在哪里?数据分析枯燥吗?
  20. browserify使用手册

热门文章

  1. SQL Server 跨数据库事务
  2. 74cms 骑士人才系统v3.5.1 正式版
  3. 如何增加MOSS 2007中list template和site template的最大值
  4. svn中提示”Files 的值 .mine 无效” 的解决方案
  5. 解决RecyclerView在ScrollView中会置顶它上面的控件
  6. XP系统的用户头像是在那个文件夹里面
  7. vue - 使用axios
  8. Ubuntu安装docker-ce,vagrant,virtualbox步骤
  9. 关于Eclipse插件开发(一)
  10. Servlet 2.0 Servlet 3.0 新特性