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>

 

posted @ 2019-06-26 19:56  林不渡  阅读(449)  评论(0编辑  收藏  举报