Render函数(4):开发可进行排序的表格组件
写在前面(6.26):
还剩社会学和运筹学两门考试就结束了大二时光啦,无论如何也回不来的大学时光里,小林经历了三次比较失败的恋爱,做出了一个人生规划(前端),拿了一次奖学金,交到了能交心的朋友,开始了一次新的恋爱。
从懒狗变得稍微勤快一点了:因为意识到,我来不及了,如果大三上学期没有掌握node、webpack、设计模式啊等等座座大山,那我可能真的错失先机了。
面试题抄了两本了,暑期的前端实习还没有着落...
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="Vue.2.6.10.js"></script>
</head>
<style>
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: center;
}
table th a{
display: inline-block;
margin: 0 4px;
cursor: pointer;
}
table th a.on{
color: #3399ff;
}
table th a:hover{
color:#3399ff;
}
</style>
<body>
<!-- 前期思路:表格组件里的内容由两个prop构成,columns用于存储每列的名称,data用于存储每行信息 -->
<div id="app">
<!-- 传递数据给组件 -->
<v-table :data='data' :columns='columns'></v-table>
</div>
</body>
<script>
Vue.component('vTable',{
props:{
columns:{
type:Array,
default:function(){
return [];
}
},
data:{
type:Array,
default:function(){
return [];
}
}
},
//要使得排序后的columns和data不至于影响原始的数据,故在组件的data中各保存一份拷贝,所有的操作将在这两个数据上完成
//在完成13行后,数据已经从父级传过来了,但是并不直接使用
data() {
return {
currentColumns:[],
currentData:[]
}
},
watch: {
data:function(){
this.makeData();
var sortedColumn = this.currentColumns.fliter(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();
},
render(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 = [];
console.log(row);
_this.currentColumns.forEach(function(cell){
//cell是对象噢,row则是具体数据对象~ 大概就是row[name]
tds.push(h('td',row[cell.key]));
console.log(cell,row[cell.key]);
});
//tds中填入这一列数据--推入trs--再下一列
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;
});
console.log(this.currentColumns);
},
makeData:function(){
this.currentData = this.data.map(function(row,index){
//标识当前行在数组中索引,后续使用
row._index = index;
return row;
});
console.log(this.currentData);
},
handleSortByAsc:function(index){
console.log(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;
})
},
},
});
//columns的每一项都是对象!title与key字段必填,用于标识各列表头标题,
//key对应data中列内容的字段名 sortable为可选项,若为true则需要进行排序
var app = new Vue({
el:"#app",
data:{
columns:[
{
title:'姓名',
key:'name'
},
{
title:'年龄',
key:'age',
sortable:true
},
],
data:[
{
name:'Harold',
age:'21',
job:'none'
},
{
name:'linbudu',
age:'22',
job:'郑茵茵饲养员'
},
{
name:'unknown',
age:'24',
job:'unknown'
}
]
}
});
//Analyse~
// 子组件中接收父组件传来的数据,并在初始化(mounted)后建立一份属于自己的(以methods中的makeColumns为例,)
// 将传入的数据通过map方法,为每一个列名对象添加_sortType、_index属性
//(多次回顾)render函数:保存指向当前组件的this,forEach方法对currentCol进行修改
//如果是可排序的(sortable==true),则除了创建 <span>title</span>外还会创建<a>用来调整排序
//否则就只创建表头
//渲染tablerow数据,最后返回表格部分
//排序:升序为例:点击对传入所在列的索引,保存该列的key值,先将每一个列名数据都设置为正常排序,再将这一列的设置为升序
//作为sort()方法比较参数的函数就比较容易了。
</script>
</html>