参考《Vue,js》实战(梁灏编著)
sort-table:实战:使用Render函数开发可排序的表格组件
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>可排序的表格组件</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div id="app" v-cloak>
<v-table :columns="columns" :data="data"></v-table>
<button @click="handleAddData">添加数据</button>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script src="table.js"></script>
<script src="index.js"></script>
</body>
</html>
index.js
var app = new Vue({
el:'#app',
data:{
columns:[
{
title:'姓名',
key: 'name'
},
{
title:'年龄',
key:'age',
sortable:true
},
{
title:'出生日期',
key:'birthday',
sortable:true
},
{
title:'地址',
key:'address'
}
],
data:[
{
name:'王小明',
age: 18,
birthday:'1999-02-21',
address:'北京市朝阳区芍药居'
},
{
name:'张小刚',
age: 25,
birthday:'1992-01-23',
address:'北京市海淀区西二旗'
},
{
name:'李小红',
age: 30,
birthday:'1987-11-10',
address:'上海市浦东新区世纪大道'
},
{
name:'周小伟',
age: 26,
birthday:'1991-10-10',
address:'深圳市南山区深南大道'
}
]
},
methods:{
handleAddData: function () {
this.data.push({
name:'刘小天',
age: 19,
birthday: '1998-05-30',
address:'北京市东城区东直门'
})
}
}
});
table.js
Vue.component('v-table', {
props: {
columns: {
type: Array,
default: function () {
return [];
}
},
data: {
type: Array,
default: function () {
return [];
}
}
},
data: function () {
return {
currentColumns: [],
currentData: []
}
},
render: function (h) {
var _this = this;
var ths = [];
this.currentColumns.forEach(function (col, index) {
if (col.sortable) {
ths.push(h('th', [
h('span', col.title),
//升序
h('a', {
class: {
on: col._sortType === 'asc'
},
on: {
click: function () {
_this.handleSortByAsc(index);
}
}
}, '↑'),
//降序
h('a', {
class: {
on: col._sortType === 'desc'
},
on: {
click: function () {
_this.handleSortByDesc(index);
}
}
}, '↓'),
]));
} else {
ths.push(h('th', col.title));
}
});
var trs = [];
this.currentData.forEach(function (row) {
var tds = [];
_this.currentColumns.forEach(function (cell) {
tds.push(h('td', row[cell.key]));
});
trs.push(h('tr', tds));
});
return h('table', [
h('thead', [
h('tr', ths)
]),
h('tbody', trs)
])
},
methods: {
makeColumns: function () {
this.currentColumns = this.columns.map(function (col, index) {
col._sortType = "normal";
col._index = index;
return col;
});
},
makeData: function () {
this.currentData = this.data.map(function (row, index) {
row._index = index;
return row;
})
},
handleSortByAsc: function (index) {
var key = this.currentColumns[index].key;
this.currentColumns.forEach(function (col) {
col._sortType = 'normal';
});
this.currentColumns[index]._sortType = 'asc';
this.currentData.sort(function (a, b) {
return a[key] > b[key] ? 1 : -1;
});
},
handleSortByDesc: function (index) {
var key = this.currentColumns[index].key;
this.currentColumns.forEach(function (col) {
col._sortType = 'normal';
});
this.currentColumns[index]._sortType = 'desc';
this.currentData.sort(function (a, b) {
return a[key] < b[key] ? 1 : -1;
})
}
},
watch: {
data: function () {
this.makeData();
var sortedColumn = this.currentColumns.filter(function (col) {
return col._sortType !== 'normal';
});
if (sortedColumn.length > 0) {
if (sortedColumn[0]._sortType === 'asc') {
this.handleSortByAsc(sortedColumn[0]._index);
} else {
this.handleSortByDesc(sortedColumn[0]._index);
}
}
}
},
mounted() {
this.makeColumns();
this.makeData();
}
});
style.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{
background: #f7f7f7;
color: #5c6b77;
font-weight: 600;
white-space: nowrap;
}
table td, table th{
padding: 8px 16px;
border: 1px solid #e9e9e9;
text-align: left;
}
table th a{
display: inline-block;
margin: 0 4px;
cursor: pointer;
}
table th a.on{
color: #3399ff;
}
table th a:hover{
color: #3399ff;
}