Vue.js学习笔记—sort-table:实战:使用Render函数开发可排序的表格组件

参考《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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值