經常使用 element-ui 的小夥伴應該對 el-table
元件非常熟悉,通常它長下面這個樣子:
<template>
<el-table :data="tableData">
<el-table-column
prop="date"
label="日期">
</el-table-column>
<el-table-column
prop="name"
label="姓名">
</el-table-column>
<el-table-column
prop="address"
label="地址">
</el-table-column>
</el-table>
</template>
<script>
export default {
data () {
return {
tableData: [{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀區金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀區金沙江路 1517 弄'
}]
}
}
}
</script>複製程式碼
上面程式碼非常正確,但總覺的少了點什麼?
沒錯,模版中 el-table-column
幾乎一致,重複寫了
使用 v-for 來優化模版中的 el-table-column
下面是採用 v-for
的版本,將每一列作為一個配置項傳入:
<template>
<el-table :data="tableData">
<el-table-column
v-for="{ prop, label } in colConfigs"
:key="prop"
:prop="prop"
:label="label">
</el-table-column>
</el-table>
</template>
<script>
export default {
data () {
this.colConfigs = [
{ prop: 'date', label: '日期' },
{ prop: 'name', label: '姓名' },
{ prop: 'address', label: '地址' }
]
return {
tableData: [{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀區金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀區金沙江路 1517 弄'
}]
}
}
}
</script>複製程式碼
這樣做的好處在於,如果想再增加一列,完全可以不用動 template
,只需要簡單的在 this.colConfigs
這個陣列中增加一個配置項 { prop: 'xxx', label: 'xxx' }
即可
雖然這樣加個配置非常簡單,擴充套件性也比之前直接寫模版好,但是如果我有一列是要渲染幾個按鈕,上面的方式就不起作用了
換句話說,我們即想要簡單的屬性可以直接加個配置項渲染出來,又希望複雜的渲染能在模版中寫出來,要怎麼實現呢?
巧用 slot,為 el-table 封裝一層
我們先來看一下封裝的元件 my-table
:
// my-table.vue
<template>
<el-table :data="data">
<template v-for="colConfig in colConfigs">
<slot v-if="colConfig.slot" :name="colConfig.slot">
<el-table-column v-bind="colConfig"></el-table-column>
</template>
</el-table>
</template>
<script>
export default {
props: ['colConfigs', 'data']
}
</script>複製程式碼
這個封裝實際上就是把前面的 colConfigs
作為一個 prop
傳入,但是跟上面例子有一點不同的是,配置項中多了一個 slot
屬性,通過這個屬性,我們就可以像文章最開始那樣在模版中寫了,用法如下:
<template>
<my-table
:data="tableData"
:col-configs="colConfigs">
<!-- slot="opt" 不能省略,需要與下面配置項中的對應 -->
<el-table-column slot="opt">
<el-button size="mini" slot-scope="{ row }">檢視</el-button>
</el-table-column>
</my-table>
</template>
<script>
export default {
data () {
this.colConfigs = [
{ prop: 'date', label: '日期' },
{ prop: 'name', label: '姓名' },
{ prop: 'address', label: '地址' },
// 模版中的元素需要對應的有 slot="opt" 屬性
{ slot: 'opt' }
]
return {
tableData: [{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀區金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀區金沙江路 1517 弄'
}]
}
}
}
</script>複製程式碼
現在我們想要增加一個列,只要加個配置項,或者加個 slot ,完美~
等等,假設我的 table 中有幾列渲染比較複雜,那幾列又都比較相似,像下面這種:
<template>
<my-table
:data="tableData"
:col-configs="colConfigs">
<el-table-column label="變化" slot="change">
<span :slot-scope="row">
{{ row['change'] > 0 ? '+' + row['change']: row['change'] }}
</span>
</el-table-column>
<el-table-column label="趨勢" slot="trend">
<span :slot-scope="row">
{{ row['trend'] > 0 ? '+' + row['trend']: row['trend'] }}
</span>
</el-table-column>
</my-table>
</template>複製程式碼
又重複寫模版了...
使用 :is="component"
我們可以為配置項再增加一個屬性 component
, 使用者可以指定 component
屬性來特殊處理某列,實現如下:
// my-table.vue
<template>
<el-table :data="data">
<template v-for="colConfig in colConfigs">
<slot v-if="colConfig.slot" :name="colConfig.slot">
<component
v-else-if="colConfig.component"
:is="config.component"
:col-config="colConfig">
</component>
<el-table-column v-else v-bind="colConfig"></el-table-column>
</template>
</el-table>
</template>
<script>
export default {
props: ['colConfigs', 'data']
}
</script>複製程式碼
然後上面的例子就可以改寫成:
<template>
<my-table
:data="tableData"
:col-configs="colConfigs">
</my-table>
</template>
<script>
const PrefixPlusText = {
props: ['colConfig'],
template: `
<el-table-column :label="colConfig.label">
<span :slot-scope="{ row }">
{{ parseInt(row[colConfig.prop]) > 0 ? '+' + row[colConfig.prop] : row[colConfig.prop] }}
</span>
</el-table-column>
`
}
export default {
data () {
this.colConfigs = [
{ prop: 'change', label: '變化' component: PrefixPlusText },
{ prop: 'name', label: '趨勢', component: PrefixPlusText },
]
return {
tableData: [{
change: '12%',
trend: '10%
}, {
change: '-12%',
trend: '-10%'
}]
}
}
}
</script>複製程式碼
總結
table 作為資料展示元件,在日常開發中經常被用到,通過這篇文章,可以看到結合 vue
的 slot/component
特性,做一層封裝,可以大大簡化 table 的使用,大部分時候只需寫一個配置屬性就可以了。
最後給一個小 demo