element-ui
虽然有el-table
组件,但是仍然需要手动写el-table-column
。
这里希望进一步抽离配置,在 el-table
的基础上封装个enhanced-el-table
组件。
使用的时候希望这样,不再需要手动写里面的el-table-column
:
<enhanced-el-table :data="tableData" :colConfigs="colConfigs" ></enhanced-el-table>
- data属性,显示的数据,
[{name:'颜酱',age:18},{...}]
- colConfigs属性,每个
column
项的配置数组,如下
colConfigs: [
{ prop: "date", label: "日期"},
{ prop: "name", label: "姓名"},
{ prop: 'address', label: '地址'}
]
可以结合表格看colConfigs
就更容易理解了,其实就是将el-table-column
上的属性换成对象的形式
本文代码后期可能较复杂,需要的话,可以去看github代码
当然文末也附上了,每个小节的具体代码,有需要也可以看看
TL;DR
- 就是写了个
enhanced-el-table
组件,充当原先的el-table
组件 - 唯一不一样的是,额外加了一个
colConfigs
,其他属性、事件、方法同el-table
组件 - 哦,如果表格的列项不足以用
colConfigs
描述的话,这边提供了slot
- 想直接看
enhanced-el-table
组件怎么用的,包括复杂情况,直接跳到本文的演示实例的优化
组件的概况
综上,enhanced-el-table
组件的大概就出来了。
el-table-column的处理
实现最开始的表格:
App.vue
里可以简单写下:
而enhanced-el-table
内部,没有colConfigs
的情况下,长这样
el-table(:data="data")
el-table-column(label="日期" prop="date")
el-table-column(label="姓名" prop="name")
el-table-column(label="地址" prop="address")
当然,有了colConfigs
,直接就循环了
el-table(:data="data")
el-table-column(v-for="config in colConfigs" v-bind="config" :key="config.prop")
优化
el-table
自身也有很多属性,这里通过简单的v-bind="$attrs"
,将enhanced-el-from
上面的属性自动到el-table
。- 同理,
v-on="$listeners"
el-table
上面的方法,稍微麻烦点,通过手动赋值- 部分列项,需要定制,通过
slotName
属性,表示不参与内部循环,需要自己写逻辑 - 经评论区 @白人酋长 提醒,多层表头的情况,这边直接用children处理,目前只写了两层逻辑,更多层的话最好使用递归,递归组件怎么写
// el-table(ref="elTable":data="data" v-bind="$attrs" v-on="$listeners")
mounted() {
const methods = [ "clearSelection", "toggleRowSelection", "toggleAllSelection", "toggleRowExpansion", "setCurrentRow", "clearSort", "clearFilter", "doLayout", "sort" ];
methods.forEach(method => (this[method] = this.$refs.elTable[method]));
}
以上逻辑将在下面的部分展示全部代码。
演示实例的优化
实例的效果:
EnhancedElTable的代码如下
<template lang="pug">
el-table(ref="elTable" :data="data" v-bind="$attrs" v-on="$listeners")
template(v-for="colConfig in colConfigs")
slot(v-if="colConfig.slotName" :name="colConfig.slotName" v-bind="colConfig")
//- 这边目前只写了两个层级,更多层级可能需要递归,请参考https://juejin.cn/post/6868560126602412045
el-table-column(v-else-if="colConfig.children && colConfig.children.length" v-bind="colConfig" :key="colConfig.label")
el-table-column(v-for="innerColConfig in colConfig.children" v-bind="innerColConfig" :key="innerColConfig.label")
el-table-column(v-else="colConfig.children && colConfig.children.length" v-bind="colConfig" :key="colConfig.label")
</template>
<script>
export default {
name: "enhanced-el-table",
props: {
data: {
type: Array,
default() {
return [];
}
},
colConfigs: {
type: Array,
default() {
return [];
}
}
},
mounted() {
const methods = [ "clearSelection", "toggleRowSelection", "toggleAllSelection", "toggleRowExpansion", "setCurrentRow", "clearSort", "clearFilter", "doLayout", "sort" ];
methods.forEach(method => (this[method] = this.$refs.elTable[method]));
}
};
</script>
App.vue的代码如下
<template lang="pug">
div#app
enhanced-el-table(:data="tableData",:colConfigs="colConfigs" ref="multipleTable" tooltip-effect="dark" style="width: 100%" @selection-change="handleSelectionChange")
//- 这里的action 需要自定制列
template(#action="colConfig")
el-table-column(v-bind="colConfig")
template(#default="scope")
el-button(size="mini" @click="handleEdit(scope.$index, scope.row)") 编辑
el-button(type="danger" size="mini" @click="handleDelete(scope.$index, scope.row)") 删除
div(style="margin-top: 20px")
el-button(@click="toggleSelection([tableData[1], tableData[2]])") 切换第二、第三行的选中状态
el-button(@click="toggleSelection()") 取消选择
div {{multipleSelection}}
</template>
<script>
import EnhancedElTable from "./components/EnhancedElTable.vue";
export default {
name: "App",
components: {
EnhancedElTable
},
data() {
return {
colConfigs: [
{ type: "selection", width: 55 },
{ prop: "date", label: "日期", width: 180 },
{ prop: "name", label: "姓名", width: 180, sortable: true },
{
label: "地址",
children: [
{ prop: "province", label: "省" },
{ prop: "city", label: "市" },
{ prop: "address", label: "地址" }
]
},
// 这里的action 需要自定制列
{ slotName: "action", label: "操作" }
],
tableData: Array.from({ length: 6 }, (v, i) => ({
date: `2016-5-${i + 1}`,
name: `王小虎${i + 1}`,
province: `省${i + 1} `,
city: `市${i + 1} `,
address: `上海市普陀区金沙江路 151${i + 1} 弄`
})),
multipleSelection: []
};
},
methods: {
toggleSelection(rows) {
if (rows) {
rows.forEach(row => {
this.$refs.multipleTable.toggleRowSelection(row);
});
} else {
this.$refs.multipleTable.clearSelection();
}
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
handleEdit(index, row) {
console.log(index, row);
},
handleDelete(index, row) {
console.log(index, row);
}
}
};
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;
}
</style>
引用
对了,还有个姊妹篇,让el-form更好用,通过配置的方式
代码
代码:组件的概况
<template lang="pug">
el-table(:data="data")
</template>
<script>
export default {
name: "enhanced-el-table",
props: {
data: {
type: Array,
default() {
return [];
}
},
colConfigs: {
type: Array,
default() {
return [];
}
}
}
};
</script>