Vue.js入门 0xE Render函数(4)Render 函数开发可排序的表格组件

    一个标准的表格由<table>、<thead>、<tbody> 、< tr >、 <th>、<td>等元素组成。
    表格组件的所有内容(表头和行数据)由两个 prop 构成 : columns 和 data。两者都是数组, columns用来描述每列的信息 , 井渲染在表头<thead> 内 ,可以指定某一列是否需要排序: data 是每一行的数据,由 columns 决定每一行里各列 的顺序。

Vue.js入门 0xE Render函数(4)Render 函数开发可排序的表格组件_第1张图片

 index.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:'2001-02-06',
                address:'北京市朝阳区芍药居'
            },
            {
                name:'李四',
                age:19,
                birthday:'2000-01-06',
                address:'北京市海淀区西二旗'
            },
            {
                name:'王五',
                age:20,
                birthday:'1999-05-08',
                address:'上海市浦东新区世纪大道'
            },
            {
                name:'赵六',
                age:21,
                birthday:'1998-11-02',
                address:'深圳市南山区深南大道'
            },
            {
                name:'马七',
                age:24,
                birthday:'1995-08-03',
                address:'杭州市下沙区职教园区'
            }
        ]
    },
    methods:{
        handleAddData:function(){
            this.data.push({
                name:'钱九',
                age:39,
                birthday:'1989-06-08',
                address:'兰州市城关区滨河路'
            });
        }
    }
});

table.js

Vue.component('vTable',{
    props:{
        //用于描述每列信息,渲染在表头
        columns:{
            type:Array,
            default:function(){
                return [];
            }
        },
        //每一行的数据,由columns决定每一行里各列的顺序
        data:{
            type:Array,
            default:function(){
                return [];
            }
        }
    },
    //数据缓存,避免操作原始数据
    data:function(){
        return {
            currentColumns:[],
            currentData:[]
        }
    },
    render:function(h){
        var _this = this;
        //这里的h就是createElement
        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:{
        /**
         * map()是JavaScript数组的一个方法,根据传入的函数重新构造一个新数组。
         * 排序分升序(asc)和降序(desc),而且同时只能对一列数据进行排序,与
         * 其他列互斥,为了标识当前列的排序状态,在map列添加上数据时,默认给每
         * 列都添加一个_sortType的字段,并赋值为normal,表示默认排序。在排序后,
         * currentData每项的顺序可能都会发生变化,所以给currentColumns和currentData
         * 的每个数据都添加_index字段,代表当前数据在原始数据中的索引。
         */
        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]0){
                if(sortedColumn[0]._sortType==='asc'){
                    this.handleSortByAsc(sortedColumn[0]._index);
                }else{
                    this.handleSortByDesc(sortedColumn[0]._index)
                }
            }
        }
    },
    mounted(){
        //v-table初始化时调用
        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;
}

 

你可能感兴趣的:(JavaScript,Vue)