Vue封裝通用table組件的完整步驟記錄
前言
隨著業(yè)務(wù)的發(fā)展和功能的增多,我們發(fā)現(xiàn)不少頁(yè)面都具備相似的功能,這里舉幾個(gè)比較俗的例子:可以多選的下拉菜單,帶輸入的對(duì)話(huà)框,日期選擇器等等,于是我們會(huì)想辦法將這些共有的功能抽取成一個(gè)個(gè)公共組件,以便能夠在不同的頁(yè)面或業(yè)務(wù)中使用。
為什么需要封裝table組件?
后臺(tái)管理系統(tǒng)表格使用頻率高,減少關(guān)于table的業(yè)務(wù)代碼,且便于后期統(tǒng)一修改、便于后期維護(hù)。如給table內(nèi)容展示,超出單元格以省略號(hào)展示等。
對(duì)于大部分的后臺(tái)管理系統(tǒng),數(shù)據(jù)表格的展示大同小異,由于不想寫(xiě)重復(fù)的代碼,所以我選擇封裝通用table組件,解放雙手。如果你的表格有一列并不是簡(jiǎn)單dom元素,比如switch按鈕,完全可以傳入一個(gè)render函數(shù),來(lái)達(dá)到目的。
第一步:定義通用組件
<!-- pro-table.vue -->
<template>
<div>
<el-table
:data="tableData"
style="width: 100%"
:stripe="tableTitle.stripe"
:border="tableTitle.border"
:fit="tableTitle.fit"
:highlight-current-row="tableTitle.highlightCurrentRow"
@selection-change="handleSelectionChange">
<!--表格第一列-->
<el-table-column
:type="firstTableCol.type"
:width="firstTableCol.width"
v-if="firstTableCol.select"
>
</el-table-column>
<!--表格其它列-->
<el-table-column v-for="(value,index) in tableCol" :key="index"
:prop="value.prop"
:label="value.label"
:width="value.width || 180">
<template slot-scope="scope">
<template v-if="!value.render">
<template v-if="value.formatter">
{{ value.formatter(scope.row, value) }}
</template>
<template v-else-if="value.getImgurl">
<el-image :src="value.getImgurl(scope.row, value)" style="width: 70px; height: 70px"
:preview-src-list="value.previewSrcList ? value.previewSrcList(scope.row, value) : value.getImgurl(scope.row, value).split(',')"/>
</template>
<template v-else>
{{ scope.row[value.prop] }}
</template>
</template>
<!--擴(kuò)展dom-->
<template v-else>
<Table :key="`cus${index}`" :render="value.render" :param="scope.row"></Table>
</template>
</template>
</el-table-column>
<!--基礎(chǔ)操作-->
<el-table-column label="操作">
<template slot-scope="scope">
<el-button type="text" v-for="(value,index) in operator" @click="value.click(scope.row, value)" :key="index">
{{ value.text }}
</el-button>
</template>
</el-table-column>
</el-table>
<!--分頁(yè)插件-->
<el-pagination
v-show="total>0"
:total="total"
:page-size.sync="pageSize"
:current-page.sync="currentPage"
:page-sizes="[10, 20, 30, 50]"
layout="total, sizes, prev, pager, next, jumper"
@current-change="handleCurrentChange"
@size-change="handleSizeChange"
v-bind="$attrs">
</el-pagination>
</div>
</template>
<script>
// render函數(shù)
import Table from './table'
export default {
components: {Table},
props: {
tableTitle: {
type: Object,
default: {
stripe: false,
border: false,
fit: true,
highlightCurrentRow: false
}
},
firstTableCol: {
type: Object,
default: {
select: false,
width: 55,
type: 'selection'
}
},
tableCol: {
type: Array,
default: []
},
tableData: {
type: Array,
default: []
},
operator: {
type: Array,
default: []
},
total: {
type: Number,
default: 0
},
page: {
type: Number,
default: 1
},
limit: {
type: Number,
default: 10
},
autoScroll: {
type: Boolean,
default: true
}
},
computed: {
currentPage: {
get () {
return this.page
},
set (val) {
this.$emit('update:page', val)
}
},
pageSize: {
get () {
return this.limit
},
set (val) {
this.$emit('update:limit', val)
}
}
},
data () {
return {
}
},
methods: {
// 監(jiān)聽(tīng)table選擇框
handleSelectionChange (selection) {
// 調(diào)用父組件對(duì)應(yīng)的方法 handleSelectionChange
this.$emit('handleSelectionChange', selection)
},
// 監(jiān)聽(tīng)每頁(yè)多少條數(shù)據(jù)(limit)
handleSizeChange (limit) {
this.$emit('pagination', {page: this.currentPage, limit: limit})
if (this.autoScroll) {
scrollTo(0, 800)
}
},
// 監(jiān)聽(tīng)當(dāng)前是第幾頁(yè)(page)
handleCurrentChange (page) {
this.$emit('pagination', {page: page, limit: this.pageSize})
if (this.autoScroll) {
scrollTo(0, 800)
}
}
}
}
</script>
<style scoped>
</style>
第二步:父組件與子組件進(jìn)行render通信
為了實(shí)現(xiàn)父組件render函數(shù)在子組件中生效,我們需要定義一個(gè)render函數(shù),在子組件中引用。
// table.js
export default {
props: {
render: {
type: Function
},
param: {
type: Object
}
},
render(h) {
return this.render(h, this.param)
}
}
第三步:使用組件
<template>
<div>
<!--
@自定義事件="父組件方法", 子組件中,this.$emit('自定義事件名稱(chēng)') 觸發(fā)父組件事件。
ref="proTable",標(biāo)記在子組件上,指向子組件實(shí)例
-->
<proTable ref="proTable" :tableTitle="tableTitle" :tableCol="tableCol" :tableData="tableData" :operator="operator"
:firstTableCol="firstTableCol"
@handleSelectionChange="handleSelectionChange"
:total="total" :page.sync="queryParams.page" :limit.sync="queryParams.limit" @pagination="getList"/>
</div>
</template>
<script>
import proTable from './pro-table'
export default {
components: {
proTable
},
data() {
return {
queryParams: {
page: 1,
limit: 10,
},
type: 'success',
total: 50,
// element-ui中對(duì)table屬性的設(shè)置
tableTitle: {
'stripe': true,
"highlightCurrentRow": true
},
// 設(shè)置table的列
tableCol: [
{ prop:'date',label:'日期'},
{ prop:'name',label:'姓名'},
{ prop:'address',label:'地址',width: 300},
{ prop:'src',label:'圖片',
getImgurl: (row, col, cellValue) => { return this.getImgurl(row)},
previewSrcList: (row, col, cellValue) => {return this.listImgUrl(row)}},
{ prop:'sex',label:'性別',
formatter: (row, col, cellVaule) => {return this.sexFormatter(row)}},
{ prop:'src',label:'圖片',
getImgurl: (row, col, cellValue) => { return this.getImgurl(row)}},
{ prop:'text',label:'函數(shù)', render: (h, params) => {return this.render(h, params)}}
],
// table的基本操作
operator: [
{'text':'詳情', click: (row, col, cellValue) => {return this.getInfo(row)}},
{'text':'刪除', click: (row, col, cellValue) => {return this.delInfo(row)}},
{'text':'編輯', click: (row, col, cellValue) => {return this.editInfo(row)}},
],
// 模擬數(shù)據(jù)
tableData: [
{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀區(qū)金沙江路 1518 弄',
sex: 0,
img:'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic2.zhimg.com%2F50%2Fv2-193cbb243dc14d3a016caaa54ba02837_hd.jpg&refer=http%3A%2F%2Fpic2.zhimg.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1628435704&t=deb5584cb9ff53fe6977f14a5e0755bb'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀區(qū)金沙江路 1517 弄',
sex: 1,
img:'https://pic1.zhimg.com/80/v2-894ab624807fd4cfa33dd4e42cc90ac8_720w.jpg?source=1940ef5c'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀區(qū)金沙江路 1519 弄',
sex: 0,
img:'xx.jpg'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀區(qū)金沙江路 1516 弄',
sex: 1,
img:'xx.jpg'
}],
firstTableCol: {
'select': true,
'type': 'selection'
}
}
},
methods: {
getInfo(val) {
// 觸發(fā)父方法
console.log("獲取詳情",val)
},
delInfo(val) {
// 觸發(fā)父方法
console.log("刪除信息",val)
},
editInfo(val) {
// 觸發(fā)父方法
console.log("編輯信息",val)
},
getImgurl(val) {
console.log(val.img)
return val.img
},
sexFormatter(val) {
return val.sex === 0 ? '男' : '女'
},
handleSelectionChange(val) {
console.log("監(jiān)聽(tīng)選擇框",val)
},
getList(queryParams) {
console.log("父級(jí)方法",queryParams)
},
listImgUrl() {
let array = [];
array.push("https://pic1.zhimg.com/80/v2-894ab624807fd4cfa33dd4e42cc90ac8_720w.jpg?source=1940ef5c");
array.push("https://cdn.pixabay.com/photo/2021/07/01/21/20/girl-6380331_960_720.jpg");
return array;
},
render(h, params) {
return h('span', null , '我是一個(gè)render組件')
}
}
}
</script>
總結(jié)
在引用組件的頁(yè)面中,我們可以給每一個(gè)table列加方法,也可以給編輯、刪除、詳情添加自定義的方法,完全實(shí)現(xiàn)定制化。也可以自定義render函數(shù)。效果圖如下:

到此這篇關(guān)于Vue封裝通用table組件的文章就介紹到這了,更多相關(guān)Vue封裝通用table組件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于Vue uniapp實(shí)現(xiàn)貪吃蛇游戲
貪吃蛇游戲想必是很多70、80后的回憶,一直到現(xiàn)在也深受大家的喜歡。本文將利用Vue+uniapp實(shí)現(xiàn)這一經(jīng)典的游戲,感興趣的可以了解一下2022-04-04
利用Vue3+Element-plus實(shí)現(xiàn)大文件分片上傳組件
在開(kāi)發(fā)中如果上傳的文件過(guò)大,可以考慮分片上傳,分片就是說(shuō)將文件拆分來(lái)進(jìn)行上傳,將各個(gè)文件的切片傳遞給后臺(tái),然后后臺(tái)再進(jìn)行合并,下面這篇文章主要給大家介紹了關(guān)于利用Vue3+Element-plus實(shí)現(xiàn)大文件分片上傳組件的相關(guān)資料,需要的朋友可以參考下2023-01-01
Vue 中使用lodash對(duì)事件進(jìn)行防抖和節(jié)流操作
這篇文章主要介紹了Vue 中使用lodash對(duì)事件進(jìn)行防抖和節(jié)流操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07
使用Vue-neo4j實(shí)現(xiàn)繪制三國(guó)人物圖譜關(guān)系
這篇文章主要介紹了使用Vue-neo4j實(shí)現(xiàn)繪制三國(guó)人物圖譜關(guān)系,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-04-04
vue?cli2?和?cli3去掉eslint檢查器報(bào)錯(cuò)的解決
這篇文章主要介紹了vue?cli2?和?cli3去掉eslint檢查器報(bào)錯(cuò)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04

