Vue封裝通用table組件的完整步驟記錄
前言
隨著業務的發展和功能的增多,我們發現不少頁面都具備相似的功能,這裡舉幾個比較俗的例子:可以多選的下拉菜單,帶輸入的對話框,日期選擇器等等,於是我們會想辦法將這些共有的功能抽取成一個個公共組件,以便能夠在不同的頁面或業務中使用。
為什麼需要封裝table組件?
後臺管理系統表格使用頻率高,減少關於table的業務代碼,且便於後期統一修改、便於後期維護。如給table內容展示,超出單元格以省略號展示等。
對於大部分的後臺管理系統,數據表格的展示大同小異,由於不想寫重復的代碼,所以我選擇封裝通用table組件,解放雙手。如果你的表格有一列並不是簡單dom元素,比如switch按鈕,完全可以傳入一個render函數,來達到目的。
第一步:定義通用組件
<!-- 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,%20value)" style="width: 70px; height: 70px" :preview-src-list="value.previewSrcList ? value.previewSrcList(scope.row, value) : value.getImgurl(scope.row,%20value).split(',')"/> </template> <template v-else> {{ scope.row[value.prop] }} </template> </template> <!--擴展dom--> <template v-else> <Table :key="`cus${index}`" :render="value.render" :param="scope.row"></Table> </template> </template> </el-table-column> <!--基礎操作--> <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> <!--分頁插件--> <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函數 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: { // 監聽table選擇框 handleSelectionChange (selection) { // 調用父組件對應的方法 handleSelectionChange this.$emit('handleSelectionChange', selection) }, // 監聽每頁多少條數據(limit) handleSizeChange (limit) { this.$emit('pagination', {page: this.currentPage, limit: limit}) if (this.autoScroll) { scrollTo(0, 800) } }, // 監聽當前是第幾頁(page) handleCurrentChange (page) { this.$emit('pagination', {page: page, limit: this.pageSize}) if (this.autoScroll) { scrollTo(0, 800) } } } } </script> <style scoped> </style>
第二步:父組件與子組件進行render通信
為瞭實現父組件render函數在子組件中生效,我們需要定義一個render函數,在子組件中引用。
// table.js export default { props: { render: { type: Function }, param: { type: Object } }, render(h) { return this.render(h, this.param) } }
第三步:使用組件
<template> <div> <!-- @自定義事件="父組件方法", 子組件中,this.$emit('自定義事件名稱') 觸發父組件事件。 ref="proTable",標記在子組件上,指向子組件實例 --> <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中對table屬性的設置 tableTitle: { 'stripe': true, "highlightCurrentRow": true }, // 設置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:'函數', 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)}}, ], // 模擬數據 tableData: [ { date: '2016-05-02', name: '王小虎', address: '上海市普陀區金沙江路 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: '上海市普陀區金沙江路 1517 弄', sex: 1, img:'https://pic1.zhimg.com/80/v2-894ab624807fd4cfa33dd4e42cc90ac8_720w.jpg?source=1940ef5c' }, { date: '2016-05-01', name: '王小虎', address: '上海市普陀區金沙江路 1519 弄', sex: 0, img:'xx.jpg' }, { date: '2016-05-03', name: '王小虎', address: '上海市普陀區金沙江路 1516 弄', sex: 1, img:'xx.jpg' }], firstTableCol: { 'select': true, 'type': 'selection' } } }, methods: { getInfo(val) { // 觸發父方法 console.log("獲取詳情",val) }, delInfo(val) { // 觸發父方法 console.log("刪除信息",val) }, editInfo(val) { // 觸發父方法 console.log("編輯信息",val) }, getImgurl(val) { console.log(val.img) return val.img }, sexFormatter(val) { return val.sex === 0 ? '男' : '女' }, handleSelectionChange(val) { console.log("監聽選擇框",val) }, getList(queryParams) { console.log("父級方法",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 , '我是一個render組件') } } } </script>
總結
在引用組件的頁面中,我們可以給每一個table列加方法,也可以給編輯、刪除、詳情添加自定義的方法,完全實現定制化。也可以自定義render函數。效果圖如下:
到此這篇關於Vue封裝通用table組件的文章就介紹到這瞭,更多相關Vue封裝通用table組件內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- vue實現表格分頁功能
- Element使用el-table組件二次封裝
- 基於element-ui表格的二次封裝實現
- vue+elementUI實現內嵌table的方法示例
- 關於el-table表格組件中插槽scope.row的使用方式