做爲一枚作後臺管理系統的前端,除了羨慕作移動端或小程序的同行,就是常常被要求作一個XX的維護頁面! 這不,這周PO又說:小X啊,給系統作個手機號歸屬地的維護頁面吧!javascript
什麼是維護頁面?就是無聊透頂的增刪改查頁面唄! 反正有現成的UI框架,而後就是對着文檔寫一些自定義標籤、配置下屬性、經過後端給的接口獲取數據填充上...前端
所以,基本的維護頁面組件大體是這個樣子:vue
<template>
<div>
<el-table :data="tableData">
<el-table-column prop="key1" label="value2"></el-table-column>
<el-table-column prop="key2" label="value2"></el-table-column>
...
<el-table-column label="操做">
<template slot-scope="scope">
<el-button @click="handleEdit">編輯</el-button>
<el-button @click="handleDel">刪除</el-button>
</template>
</el-table-column>
</div>
</template>
複製代碼
最終呈現的頁面: java
可是,此次終於爆發了,不想再作這種重複性工做了!(固然不是拒毫不作) 想着,要是經過配置JSON,直接生成頁面就行了! 尋思着,對Element-UI的Tabel組件再作一層封裝! 最終,只要配置如下JSON參數,就能夠自動生成須要的頁面:小程序
const options = {
table: {
columns: [
{
prop: 'value1',
label: 'key1'
},
{
prop: 'value2',
label: 'key2'
}
],
handle: getData
}
};
複製代碼
這是最基本的配置,但Element-UI的Table組件自己還支持不少配置參數,這些配置若也在JSON中,也要正常做用。所以,template模板寫法並不適用,或者說自由度不高,因此採用了JSX的寫法:後端
export default {
props: {
options: Object
},
data() {
return {
tableData: []
};
};
render(h) {
const tpl = <div></div>;
const tableTpl = <el-table data={ this.tableData }></el-table>; const options = this.options; const componentOptions = tableTpl.componentOptions; // 遍歷傳入的屬性,配置在原生的Element Table組件上 (let option in options.table) { componentOptions.propsData[option] = options.table[option]; } options.table.columns.forEach(column => { const columnTpl = <column options={ column }></column>; componentOptions.children.push(columnTpl); }); tpl.children.push(tableTpl); return tpl; }, methods: { getData() { const options = this.options; const params = {}; options.handle && options.handle(params).then(res => { if (res.status === 0) { this.tableData = res.result.Body; } }); } }, created() { this.getData(); } } 複製代碼
根元素用div,而不直接用el-table,是方便爲了之後加入分頁與表單篩選。框架
其實,表格的最後一列,雖然做爲維護頁面基本就是編輯與刪除,但也不保證沒有變更!需求這種東西誰知道呢。所以,將最後一列的內容與邏輯都拋出來,不放在組件裏實現,但要保證其擁有原先的做用域。這裏,就須要藉助vue的做用域插槽,好比咱們是這麼使用組件的:函數
<custom-table :options="options">
<template slot-scope="scope"> <el-button size="small" type="text" @click="handleClick(scope)">編輯</el-button> </template> </custom-table> 複製代碼
這裏的點擊事件處理方法的參數scope,就是原生el-table-column組件的做用域,即 scope = { row, column, $index }。 所以,須要對el-table-column也作一層封裝:ui
components: {
Column: {
props: {
options: Object
},
render(h) {
const tpl = <el-table-column ></el-table-column>; const options = this.options; const componentOptions = tpl.componentOptions; for (let option in options) { if (option === 'slot') { const slot = this.$parent.$parent.$scopedSlots.default; tpl.data['scopedSlots'] = { default: scope => { return [slot(scope)]; } }; } else { componentOptions.propsData[option] = options[option]; } } return tpl; } } 複製代碼
這裏要注意,獲取的slot是一個函數,須要執行再傳入。this
到這裏,其實只是知足了最最基本的數據展現,還有許多功能並未實現,好比數據行的選擇之類的。以後的實現會加入分頁與表單!
如有寫的很差的地方,歡迎指出!