element-ui封裝一個(gè)Table模板組件的示例
大家在做后臺(tái)管理系統(tǒng)的時(shí)候,寫(xiě)的最多的可能就是表格頁(yè)面了,一般分三部分:搜索功能區(qū)、表格內(nèi)容區(qū)和分頁(yè)器區(qū)。一般這些功能都是使用第三方組件庫(kù)實(shí)現(xiàn),比如說(shuō)element-ui,或者vuetify。這兩個(gè)組件庫(kù)都各有各的優(yōu)點(diǎn),但就table組件來(lái)說(shuō),我還是比較喜歡vuetify的實(shí)現(xiàn),不用手寫(xiě)一個(gè)個(gè)column,只要傳入headers的配置數(shù)組就行,甚至分頁(yè)器都內(nèi)置在了table組件里,用起來(lái)十分方便。有興趣可以看看:vuetify data table。
上面是一個(gè)經(jīng)典的用element-ui開(kāi)發(fā)的table頁(yè)面,而且實(shí)際工作中如果每個(gè)table頁(yè)面都寫(xiě)一遍,重復(fù)代碼太多了,所以不妨寫(xiě)一個(gè)table模板組件,減少重復(fù)代碼。我的思路是這樣的:
搜索功能區(qū):
提供searchBar插槽,可以自定義搜索輸入框,搜索、重置按鈕必有,新增按鈕通過(guò)props控制顯隱。這里對(duì)應(yīng)的代碼如下:
genSearchBar() { if (this.noSearchBar || !this.$scopedSlots.searchBar) return ''; return ( <el-form class="seatch-form" inline={true} label-width="100"> {this.$scopedSlots.searchBar()} <el-button class="filter-item" icon="el-icon-search" type="primary" onClick={this.handleSearchBtnClick} > 查詢 </el-button> <el-button class="filter-item" icon="el-icon-refresh" onClick={this.handleResetBtnClick} > 重置 </el-button> <el-button class="filter-item" icon="el-icon-plus" type="primary" v-show={this.showAddBtn} onClick={this.handleAddBtnClick} > 新增 </el-button> </el-form> ); }
表格內(nèi)容區(qū):
通過(guò)傳入headers自動(dòng)生成columns,參數(shù)如下:
{ label: '性別', prop: 'sex', width: '180', filter: 'sexFilter' }
可對(duì)應(yīng)如下代碼:
<el-table-column prop="sex" label="性別" width="180"> <template slot-scope="scope">{{scope.row.sex | sexFilter}}</template> </el-table-column>
注意,只支持全局filter。
如果你想自定義column,也提供tableColumn插槽,支持自定義column,可以如下配置:
{ prop: 'action' }
<el-table-column prop="action" label="操作" width="180"> <template slot-scope="scope"> <el-button>編輯</el-button> <el-button>刪除</el-button> </template> </el-table-column>
這樣,就會(huì)按傳入的prop匹配對(duì)應(yīng)的column,十分方便。
實(shí)現(xiàn)代碼如下:
genTableSlot(h) { let customeColumns = this.$scopedSlots.tableColumn ? this.$scopedSlots.tableColumn() : []; return this.headers.map((item) => { // 根據(jù)item.prop判斷是否使用傳入的插槽內(nèi)容 let foundItem = customeColumns.find( (ele) => ele.componentOptions && ele.componentOptions.propsData.prop === item.prop ); return foundItem ? foundItem : h('el-table-column', { props: { ...item, }, scopedSlots: { default: (props) => { // 根據(jù)傳入的全局filter處理column數(shù)據(jù) let filter = this.$options.filters[ item.filter ]; let itemValue = props.row[item.prop]; return h( 'span', filter ? filter(itemValue) : itemValue ); }, }, }); }); }
genTable(h) { return h( 'el-table', { ref: 'tableRef', props: { ...this.$attrs, data: this.data, }, on: { 'selection-change': (val) => { this.$emit('selection-change', val); }, }, }, [...this.genTableSlot(h)] ); }
分頁(yè)器區(qū):
如無(wú)特殊需求,分頁(yè)器功能一致,所以直接內(nèi)置。
實(shí)現(xiàn)代碼如下:
genPagination() { return ( <div class="pagination-wrap"> <el-pagination layout="total,prev,pager,next,jumper" current-page={this.current} page-size={this.pageSize} total={this.total} {...{ on: { 'current-change': this.handleCurrentChange }, }} ></el-pagination> </div> ); }
最后附完整代碼和demo:
<script> export default { name: 'TableTemplate', props: { data: { type: Array, default: () => [], required: true, }, headers: { type: Array, default: () => [], required: true, }, current: { type: Number, default: 1, }, pageSize: { type: Number, default: 10, }, total: { type: Number, default: 0, }, noSearchBar: Boolean, showAddBtn: Boolean, }, mounted() { this.$nextTick(() => { this.$emit('search'); }); }, methods: { genSearchBar() { if (this.noSearchBar || !this.$scopedSlots.searchBar) return ''; return ( <el-form class="seatch-form" inline={true} label-width="100"> {this.$scopedSlots.searchBar()} <el-button class="filter-item" icon="el-icon-search" type="primary" onClick={this.handleSearchBtnClick} > 查詢 </el-button> <el-button class="filter-item" icon="el-icon-refresh" onClick={this.handleResetBtnClick} > 重置 </el-button> <el-button class="filter-item" icon="el-icon-plus" type="primary" v-show={this.showAddBtn} onClick={this.handleAddBtnClick} > 新增 </el-button> </el-form> ); }, genTableSlot(h) { let customeColumns = this.$scopedSlots.tableColumn ? this.$scopedSlots.tableColumn() : []; return this.headers.map((item) => { // 根據(jù)item.prop判斷是否使用傳入的插槽內(nèi)容 let foundItem = customeColumns.find( (ele) => ele.componentOptions && ele.componentOptions.propsData.prop === item.prop ); return foundItem ? foundItem : h('el-table-column', { props: { ...item, }, scopedSlots: { default: (props) => { let filter = this.$options.filters[ item.filter ]; let itemValue = props.row[item.prop]; return h( 'span', filter ? filter(itemValue) : itemValue ); }, }, }); }); }, genTable(h) { return h( 'el-table', { ref: 'tableRef', props: { ...this.$attrs, data: this.data, }, on: { 'selection-change': (val) => { this.$emit('selection-change', val); }, }, }, [...this.genTableSlot(h)] ); }, genPagination() { return ( <div class="pagination-wrap"> <el-pagination layout="total,prev,pager,next,jumper" current-page={this.current} page-size={this.pageSize} total={this.total} {...{ on: { 'current-change': this.handleCurrentChange }, }} ></el-pagination> </div> ); }, resetPagination() { this.$emit('update:current', 1); }, handleCurrentChange(val) { this.$emit('update:current', val); this.$emit('search'); }, handleSearchBtnClick() { this.$emit('search'); }, handleResetBtnClick() { this.resetPagination(); this.$emit('reset'); }, handleAddBtnClick() { this.$emit('add'); }, getTableRef() { return this.$refs.tableRef; }, }, render(h) { return ( <div> {this.genSearchBar()} {this.genTable(h)} {this.genPagination()} </div> ); }, }; </script> <style scoped> .seatch-form { text-align: left; } .pagination-wrap { margin-top: 20px; text-align: right; } </style>
Demo:
<template> <div> <table-template border :headers="headers" :data="tableData" :current.sync="current" :total="total" ref="tableTemplate" showAddBtn @search="handleSearch" @reset="handleReset" @add="handleAdd" @selection-change="handleSelectionChange" > <template #searchBar> <el-form-item label="姓名:" prop="title"> <el-input class="filter-item" v-model="searchForm.title" ></el-input> </el-form-item> </template> <template #tableColumn> <el-table-column prop="selection" type="selection" width="55" ></el-table-column> <el-table-column prop="test" label="姓名" width="180"> <template slot-scope="scope"> <el-popover trigger="hover" placement="top"> <p>姓名:{{ scope.row.name }}</p> <p>住址:{{ scope.row.address }}</p> <div slot="reference" class="name-wrapper"> <el-tag size="medium">{{scope.row.name}}</el-tag> </div> </el-popover> </template> </el-table-column> </template> </table-template> </div> </template> <script> import TableTemplate from './TableTemplate'; export default { name: 'Demo', components: { TableTemplate, }, data() { return { current: 1, total: 100, headers: [ { prop: 'selection', }, { label: '姓名', prop: 'name', width: '100', }, { label: '年齡', prop: 'year', }, { label: '性別', prop: 'sex', width: 'sexFilter', }, { prop: 'test', }, ], tableData: [ { name: 'curry', year: 18, sex: 'female', address: '天安門', }, ], searchForm: { title: '', }, }; }, methods: { handleSearch() { console.log(this.current); }, handleReset() { this.searchForm = { title: '', }; }, handleAdd() { console.log('添加'); }, handleSelectionChange(val) { console.log(val); }, getTableRef() { console.log(this.$refs.tableTemplate.getTableRef()); }, }, }; </script>
以上就是element-ui封裝一個(gè)Table模板組件的示例的詳細(xì)內(nèi)容,更多關(guān)于element-ui封裝組件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Vue過(guò)濾器,生命周期函數(shù)和vue-resource簡(jiǎn)單介紹
這篇文章主要介紹了Vue過(guò)濾器,生命周期函數(shù)和vue-resource簡(jiǎn)單介紹,幫助大家更好的理解和使用vue,感興趣的朋友可以了解下2021-01-01前端Vue項(xiàng)目部署到服務(wù)器的全過(guò)程以及踩坑記錄
使用Vue做前后端分離項(xiàng)目時(shí),通常前端是單獨(dú)部署,用戶訪問(wèn)的也是前端項(xiàng)目地址,因此前端開(kāi)發(fā)人員很有必要熟悉一下項(xiàng)目部署的流程,下面這篇文章主要給大家介紹了關(guān)于前端Vue項(xiàng)目部署到服務(wù)器的全過(guò)程以及踩坑記錄的相關(guān)資料,需要的朋友可以參考下2023-05-05vue3?element?plus?table?selection展示數(shù)據(jù),默認(rèn)選中功能方式
這篇文章主要介紹了vue3?element?plus?table?selection展示數(shù)據(jù),默認(rèn)選中功能方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07使用開(kāi)源Cesium+Vue實(shí)現(xiàn)傾斜攝影三維展示功能
這篇文章主要介紹了使用開(kāi)源Cesium+Vue實(shí)現(xiàn)傾斜攝影三維展示,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07快速解決vue在ios端下點(diǎn)擊響應(yīng)延時(shí)的問(wèn)題
今天小編就為大家分享一篇快速解決vue在ios端下點(diǎn)擊響應(yīng)延時(shí)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-08-08