让el-table更好用,通过配置的方式
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>