Vue:表格組件vue-easytable的使用

需求背景

在移動端頁面開發上,有些場景需要使用表格。可能涉及表格的展示、編輯、單元格拆分、單元格合併、刪除、行列凍結。和移動端相比,H5開發效率較快,本文也只討論在移動端H5開發上表格組件的使用。

 

方案選擇

1、hansontable

功能強大,但商業使用收費

2、element

功能強大,更適合網頁端

3、vue-easytable

功能較強大,基本滿足大部分場景需求

基於以上,選擇了vue-easytable方案

 

使用說明

1、文檔地址

Github:https://github.com/huangshuwei/vue-easytable

API:http://doc.huangsw.com/vue-easytable/app.html#/install

2、安裝

npm install vue-easytable --save

引入依賴:

import 'vue-easytable/libs/themes-base/index.css'
import {VTable, VPagination} from 'vue-easytable'
​
//組件中註冊
components: {
   VTable, VPagination
}

3、單元格可編輯

使用方式:

  • 通過給 columns 設置 isEdit:true 開啓單元格編輯。

  • cell-edit-done回調函數,回調參數爲 newValueoldValuerowIndexrowDatafield,並給table-data當前編輯的列賦值

示例代碼:

<template>
    <v-table is-horizontal-resize style="width:100%" :columns="columns" :table-data="tableData" row-hover-color="#eee" row-click-color="#edf7ff" :cell-edit-done="cellEditDone"></v-table>
</template>

<style>
    .cell-edit-color{
        color:#2db7f5;
        font-weight: bold;
    }
</style>
<script>

    export default{
        data() {
            return {
                  tableData: [
                        {"name":"趙偉","tel":"156*****1987","hobby":"鋼琴、書法、唱歌","address":"上海市黃浦區金陵東路569號17樓"},
                        {"name":"李偉","tel":"182*****1538","hobby":"鋼琴、書法、唱歌","address":"上海市奉賢區南橋鎮立新路12號2樓"},
                        {"name":"孫偉","tel":"161*****0097","hobby":"鋼琴、書法、唱歌","address":"上海市崇明縣城橋鎮八一路739號"},
                        {"name":"周偉","tel":"197*****1123","hobby":"鋼琴、書法、唱歌","address":"上海市青浦區青浦鎮章浜路24號"},
                        {"name":"吳偉","tel":"183*****6678","hobby":"鋼琴、書法、唱歌","address":"上海市松江區樂都西路867-871號"}
                     ],
                    columns:  [
                             {field: 'name', title:'姓名', width: 80, titleAlign: 'center',columnAlign:'center',isEdit:true,
                              formatter: function (rowData,rowIndex,pagingIndex,field) {

                                   return `<span class='cell-edit-color'>${rowData[field]}</span>`;
                               },isResize:true},
                             {field: 'tel', title: '手機號碼', width: 150, titleAlign: 'center',columnAlign:'center',isEdit:true,isResize:true},
                             {field: 'hobby', title: '愛好', width: 150, titleAlign: 'center',columnAlign:'center',isEdit:true,isResize:true},
                             {field: 'address', title: '地址', width: 280, titleAlign: 'center',columnAlign:'left',isEdit:true,isResize:true}
                     ]
            }
        },
        methods:{

            // 單元格編輯回調
            cellEditDone(newValue,oldValue,rowIndex,rowData,field){

                this.tableData[rowIndex][field] = newValue;

                // 接下來處理你的業務邏輯,數據持久化等...
            }
        }
    }
</script>

4、行列合併

 使用方式:

  • 通過傳入 cell-merge 回調函數設置要合併的單元格

  • 找到要合併的列使用colspan,找到要合併的行使用rowspan

  • 通過設置 content爲合併後單元格內容(html),也可通過 componentName組件作爲合併後單元格內容

示例代碼:

<template>
    <div>
        <v-table :width="1100" :height="300" :columns="columns" :table-data="tableData" even-bg-color="#f4f4f4" row-hover-color="#eee" row-click-color="#edf7ff" :cell-merge="cellMerge"></v-table>
    </div>
</template>


<script>
    import Vue from 'vue'

    export default{
        name: 'frozen-title-columns',
        data(){
            return {
                tableData: [{"name":"趙偉","gender":"男","birthday":'1963-7-9',"height":"183","email":"[email protected]","tel":"156*****1987","hobby":"鋼琴、書法、唱歌","address":"上海市黃浦區金陵東路569號17樓"},
                            {"name":"李偉","gender":"男","birthday":'2003-12-7',"height":"166","email":"[email protected]","tel":"182*****1538","hobby":"鋼琴、書法、唱歌","address":"上海市奉賢區南橋鎮立新路12號2樓"},
                            {"name":"孫偉","gender":"女","birthday":'1993-12-7',"height":"186","email":"[email protected]","tel":"161*****0097","hobby":"鋼琴、書法、唱歌","address":"上海市崇明縣城橋鎮八一路739號"},
                            {"name":"周偉","gender":"女","birthday":'1993-12-7',"height":"188","email":"[email protected]","tel":"197*****1123","hobby":"鋼琴、書法、唱歌","address":"上海市青浦區青浦鎮章浜路24號"},
                            {"name":"吳偉","gender":"男","birthday":'1993-12-7',"height":"160","email":"[email protected]","tel":"183*****6678","hobby":"鋼琴、書法、唱歌","address":"上海市松江區樂都西路867-871號"},
                            {"name":"馮偉","gender":"女","birthday":'1993-12-7',"height":"168","email":"[email protected]","tel":"133*****3793","hobby":"鋼琴、書法、唱歌","address":"上海市金山區龍勝路143號一層"},
                            {"name":"褚偉","gender":"男","birthday":'1993-12-7',"height":"170","email":"[email protected]","tel":"189*****2345","hobby":"鋼琴、書法、唱歌","address":"上海市閔行區都市路2988號2樓"},],
                columns:[
                       {field: 'name', title:'姓名', width: 150, titleAlign: 'center',columnAlign:'center', isFrozen: true},
                       {field: 'gender', title:'性別', width: 150, titleAlign: 'center',columnAlign:'center', isFrozen: true},
                       {field: 'tel', title: '手機號碼', width: 180, titleAlign: 'center',columnAlign:'center', isFrozen: false},
                       {field: 'birthday', title: '出生日期', width: 180, titleAlign: 'center',columnAlign:'center'},
                       {field: 'hobby', title: '愛好', width: 380, titleAlign: 'center',columnAlign:'center'},
                       {field: 'address', title: '地址', width: 430, titleAlign: 'center',columnAlign:'left'}
                     ]
            }
        },
        methods: {

            cellMerge(rowIndex,rowData,field){
                if (field === 'name' && rowData[field] === '李偉') {
                    return {
                        colSpan: 2,
                        rowSpan: 1,
                        content: '<span style="color:red">單元格 colSpan</span>',
                        componentName: ''

                    }
                } else if (rowIndex === 3 && field === 'gender') {

                    return {
                        colSpan: 1,
                        rowSpan: 3,
                        content: '<span style="color:red">單元格 rowSpan</span>',
                        componentName: ''
                    }

                }else if (rowIndex === 2 && field === 'birthday') {

                        return {
                            colSpan: 2,
                            rowSpan: 3,
                            content:'',
                            componentName:'table-cell-merge',
                        }
                }
            }
        }
    }

        // 自定義列組件
        Vue.component('table-cell-merge',{
            template:`<span style="color:red">
               單元格 rowSpan 和 colSpan 同時使用
            </span>`,
            props:{
                rowData:{
                    type:Object
                },
                field:{
                    type:String
                },
                index:{
                    type:Number
                }
            }
        })
</script>

5、自定義列

 使用方式:

  • 通過 formatter函數對當前數據進行簡單的加工處理,這個方法接收rowDatarowIndex,pagingIndex,field作爲回調數據;

  • 通過componentName傳遞一個vue組件,這個自定義組件會接收到rowDatafieldindex作爲回調數據;

  • 通過傳入事件on-custom-comp實現子組件與父組件通訊的目的;

示例代碼:

<template>
    <v-table is-horizontal-resize style="width:100%" :columns="columns" :table-data="tableData" row-hover-color="#eee" row-click-color="#edf7ff" @on-custom-comp="customCompFunc"></v-table>
</template>

<script>

    import Vue from 'vue'

    export default{
        data() {
            return {
                tableData: [
                        {"name":"趙偉","tel":"156*****1987","hobby":"鋼琴、書法、唱歌","address":"上海市黃浦區金陵東路569號17樓"},
                        {"name":"李偉","tel":"182*****1538","hobby":"鋼琴、書法、唱歌","address":"上海市奉賢區南橋鎮立新路12號2樓"},
                        {"name":"孫偉","tel":"161*****0097","hobby":"鋼琴、書法、唱歌","address":"上海市崇明縣城橋鎮八一路739號"},
                        {"name":"周偉","tel":"197*****1123","hobby":"鋼琴、書法、唱歌","address":"上海市青浦區青浦鎮章浜路24號"},
                        {"name":"吳偉","tel":"183*****6678","hobby":"鋼琴、書法、唱歌","address":"上海市松江區樂都西路867-871號"}
                     ],
                    columns: [
                        {
                            field: 'custome', title:'序號', width: 50, titleAlign: 'center', columnAlign: 'center',
                            formatter: function (rowData,rowIndex,pagingIndex,field) {
                                return rowIndex < 3 ? '<span style="color:red;font-weight: bold;">' + (rowIndex + 1) + '</span>' : rowIndex + 1
                            }, isFrozen: true,isResize:true
                        },
                        {field: 'name', title:'姓名', width: 80, titleAlign: 'center',columnAlign:'center',isResize:true},
                        {field: 'tel', title: '手機號碼', width: 150, titleAlign: 'center',columnAlign:'center',isResize:true},
                        {field: 'hobby', title: '愛好', width: 150, titleAlign: 'center',columnAlign:'center',isResize:true},
                        {field: 'address', title: '地址', width: 230, titleAlign: 'center',columnAlign:'left',isResize:true},
                        {field: 'custome-adv', title: '操作',width: 200, titleAlign: 'center',columnAlign:'center',componentName:'table-operation',isResize:true}
                    ]

            }
        },
        methods:{
            customCompFunc(params){

                console.log(params);

                if (params.type === 'delete'){ // do delete operation

                    this.$delete(this.tableData,params.index);

                }else if (params.type === 'edit'){ // do edit operation

                    alert(`行號:${params.index} 姓名:${params.rowData['name']}`)
                }

            }
        }
    }

    // 自定義列組件
    Vue.component('table-operation',{
        template:`<span>
        <a href="" @click.stop.prevent="update(rowData,index)">編輯</a>&nbsp;
        <a href="" @click.stop.prevent="deleteRow(rowData,index)">刪除</a>
        </span>`,
        props:{
            rowData:{
                type:Object
            },
            field:{
                type:String
            },
            index:{
                type:Number
            }
        },
        methods:{
            update(){

               // 參數根據業務場景隨意構造
               let params = {type:'edit',index:this.index,rowData:this.rowData};
               this.$emit('on-custom-comp',params);
            },

            deleteRow(){

                // 參數根據業務場景隨意構造
                let params = {type:'delete',index:this.index};
                this.$emit('on-custom-comp',params);

            }
        }
    })
</script>

6、固定表頭固定列

 使用方式:

  • 固定表頭:只需要設置height屬性即可,如果設置的高度大於實際表格的高度,將以實際表格高度爲準

  • 固定列:通過給需要固定的列,設置 isFrozen: true 即可

  • 固定複雜表頭和固定列:

    表頭合併需要設置 titleRows對象;

    titleRows數組中的每一項代表表頭的每一行,通過fields屬性設置當前要合併的表頭列,如果需要和並列則使用colspan,如果需要行合併則設置rowspan

示例代碼:

<template>
   <v-table :width="1100" :height="280" even-bg-color="#f2f2f2" :title-rows="titleRows" :columns="columns" :table-data="tableData" row-hover-color="#eee" row-click-color="#edf7ff"></v-table>
</template>

<style>
    .title-cell-class-name-test1 {
        background-color: #2db7f5;
    }
    .title-cell-class-name-test2 {
        background-color: #f60;
    }
</style>
<script>

    export default{
        data(){
            return {
                multipleSort: false,
                tableData: [
                        {"name":"趙偉","gender":"男","height":"183","email":"[email protected]","tel":"156*****1987","hobby":"鋼琴、書法、唱歌","address":"上海市黃浦區金陵東路569號17樓"},
                        {"name":"李偉","gender":"男","height":"166","email":"[email protected]","tel":"182*****1538","hobby":"鋼琴、書法、唱歌","address":"上海市奉賢區南橋鎮立新路12號2樓"},
                        {"name":"孫偉","gender":"女","height":"186","email":"[email protected]","tel":"161*****0097","hobby":"鋼琴、書法、唱歌","address":"上海市崇明縣城橋鎮八一路739號"},
                        {"name":"周偉","gender":"女","height":"188","email":"[email protected]","tel":"197*****1123","hobby":"鋼琴、書法、唱歌","address":"上海市青浦區青浦鎮章浜路24號"},
                        {"name":"吳偉","gender":"男","height":"160","email":"[email protected]","tel":"183*****6678","hobby":"鋼琴、書法、唱歌","address":"上海市松江區樂都西路867-871號"},
                        {"name":"馮偉","gender":"女","height":"168","email":"[email protected]","tel":"133*****3793","hobby":"鋼琴、書法、唱歌","address":"上海市金山區龍勝路143號一層"}
                ],
                columns: [
                     {
                        field: 'custome', width: 50, titleAlign: 'center', columnAlign: 'center',
                        formatter: function (rowData, index) {
                            return index < 3 ? '<span style="color:red;font-weight: bold;">' + (index + 1) + '</span>' : index + 1
                        }, isFrozen: true
                    },
                    {field: 'name', width: 100, columnAlign: 'center', isFrozen: true},
                    {field: 'gender', width: 150, columnAlign: 'center', isFrozen: true},
                    {field: 'height', width: 150, columnAlign: 'center', isFrozen: true},
                    {field: 'tel', width: 190, columnAlign: 'center'},
                    {field: 'email', width: 230, columnAlign: 'center'},
                    {field: 'hobby', width: 230, columnAlign: 'center'},
                    {field: 'address', width: 330, columnAlign: 'left'}
                ],

                titleRows: [
                             [{fields: ['custome'], title: '排序', titleAlign: 'center', rowspan: 2},
                              {fields: ['name', 'gender', 'height'], title: '基礎信息', titleAlign: 'center', colspan: 3},
                              {fields: ['tel', 'email'], title: '聯繫方式', titleAlign: 'center', colspan: 2},
                              {fields: ['hobby','address'], title: '愛好及地址', titleAlign: 'center', rowspan: 2,colspan: 2}],

                             [{fields: ['name'], title: '姓名', titleAlign: 'center'},
                              {fields: ['gender'], title: '性別', titleAlign: 'center', orderBy: 'asc'},
                              {fields: ['height'], title: '身高', titleAlign: 'center', orderBy: 'desc'},
                              {fields: ['tel'], title: '手機號碼', titleAlign: 'center'},
                              {fields: ['email'], title: '郵箱', titleAlign: 'center'}],

                             [{fields: ['custome','name','gender','height'], title: '平均值', titleAlign: 'center', colspan: 4,titleCellClassName:'title-cell-class-name-test1'},
                              {fields: ['tel'], title: '000', titleAlign: 'center',titleCellClassName:'title-cell-class-name-test2'},
                              {fields: ['email'], title: '111', titleAlign: 'center',titleCellClassName:'title-cell-class-name-test2'},
                              {fields: ['hobby'], title: '222', titleAlign: 'center',titleCellClassName:'title-cell-class-name-test2'},
                              {fields: ['address'], title: '333', titleAlign: 'center',titleCellClassName:'title-cell-class-name-test2'}]
                           ]
            }
        }
    }
</script>

7、關於排序、分頁等功能具體見API地址.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章