需求背景
在移動端頁面開發上,有些場景需要使用表格。可能涉及表格的展示、編輯、單元格拆分、單元格合併、刪除、行列凍結。和移動端相比,H5開發效率較快,本文也只討論在移動端H5開發上表格組件的使用。
方案選擇
功能強大,但商業使用收費
2、element
功能強大,更適合網頁端
功能較強大,基本滿足大部分場景需求
基於以上,選擇了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
回調函數,回調參數爲newValue
、oldValue
、rowIndex
、rowData
、field
,並給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
函數對當前數據進行簡單的加工處理,這個方法接收rowData
、rowIndex
,pagingIndex
,field
作爲回調數據; -
通過
componentName
傳遞一個vue組件,這個自定義組件會接收到rowData
、field
、index
作爲回調數據; -
通過傳入事件
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>
<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>