Those of you who use Element-UI regularly will be familiar with the El-Table component, which usually looks like this:
<template>
<el-table :data="tableData">
<el-table-column
prop="date"
label="Date">
</el-table-column>
<el-table-column
prop="name"
label="Name">
</el-table-column>
<el-table-column
prop="address"
label="Address">
</el-table-column>
</el-table>
</template>
<script>
export default {
data () {
return {
tableData: [{
date: '2016-05-02',
name: 'Wang Xiaohu',
address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai
}, {
date: '2016-05-04',
name: 'Wang Xiaohu',
address: Lane 1517, Jinshajiang Road, Putuo District, Shanghai
}]
}
}
}
</script>Copy the code
The above code is very correct, but something is missing?
Yes, the el-table-column in the template is almost identical. It’s repeated
Use V-for to optimize el-table-column in the template
Here is the v-for version, passing each column as a configuration item:
<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: 'date' },
{ prop: 'name', label: 'name' },
{ prop: 'address', label: 'address'}]return {
tableData: [{
date: '2016-05-02',
name: 'Wang Xiaohu',
address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai
}, {
date: '2016-05-04',
name: 'Wang Xiaohu',
address: Lane 1517, Jinshajiang Road, Putuo District, Shanghai
}]
}
}
}
</script>Copy the code
The nice thing about this is that if you want to add another column, you can leave the template out of the array and simply add a configuration item {prop: ‘XXX ‘, label:’ XXX ‘} to the array this.colConfigs
Although it’s easy to add a configuration like this and it’s much more scalable than writing the template directly, it doesn’t work if I have a column that renders a few buttons
In other words, we want simple attributes that can be rendered directly with a configuration item, but we also want complex renderings that can be written in a template. How do we do that?
Use slot skillfully to encapsulate a layer for el-Table
Let’s take a look at the encapsulated component 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>Copy the code
This wrapper actually passes colConfigs as a prop, but differs a little from the previous example by adding a slot property to the configuration item. With this property, we can use the template as we did at the beginning of this article.
<template>
<my-table
:data="tableData"
:col-configs="colConfigs"> <! -- slot="opt"The value must correspond to the following configuration items: --> <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: 'date' },
{ prop: 'name', label: 'name' },
{ prop: 'address', label: 'address'}, // Elements in the template need to correspond to slot="opt"Attributes {slot:'opt'}]return {
tableData: [{
date: '2016-05-02',
name: 'Wang Xiaohu',
address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai
}, {
date: '2016-05-04',
name: 'Wang Xiaohu',
address: Lane 1517, Jinshajiang Road, Putuo District, Shanghai
}]
}
}
}
</script>Copy the code
Now we want to add a column, just add a configuration item, or add a slot, perfect
Wait, let’s say I have a table with a few columns that are complicated to render, and those columns are all similar, like this:
<template>
<my-table
:data="tableData"
:col-configs="colConfigs">
<el-table-column label="Change" slot="change">
<span :slot-scope="row">
{{ row['change'] > 0?'+' + row['change']: row['change'] }}
</span>
</el-table-column>
<el-table-column label="Trends" slot="trend">
<span :slot-scope="row">
{{ row['trend'] > 0?'+' + row['trend']: row['trend'] }}
</span>
</el-table-column>
</my-table>
</template>Copy the code
Writing templates again…
Use: is = “component”
We can add a component attribute to the configuration item. The user can specify the Component attribute to handle a particular column as follows:
// 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>Copy the code
The above example can then be rewritten as:
<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: 'change' component: PrefixPlusText },
{ prop: 'name', label: 'trend', component: PrefixPlusText },
]
return {
tableData: [{
change: '12%',
trend: '10% }, { change: '- 12%', trend: '- 10%' }] } } } Copy the code
conclusion
Table as a data presentation component is often used in daily development. In this article, we can see that combining the slot/ Component feature of VUE and a layer of encapsulation can greatly simplify the use of tables. Most of the time, only one configuration property is needed.
And then I’ll give you a little demo