基于 Element-plus Table 封装的易用, 统一, 敌对的 Vue Table 组件
- 组件源码
- 组件文档
-
原文
Why
用过 Element UI Table 的同学都晓得用 Table 组件时须要用到el-table-column
,它是和 html 混写在一起的, 如果很多列的话,就须要一个个写配置, 否则就须要用到循环。如果列配置内容有依据不同条件展现不同款式内容的话, 就须要在插槽外面做判断, 比方这样两种编辑状态:
比方在插槽外面做配置, 如下代码:
<el-table-column label="操作">
<template #default="scope">
<div v-if="scope.row._edit">
<el-button type="primary" @click="handleSave(scope)"> 保留 </el-button>
<el-button @click="handleCancle(scope)"> 勾销 </el-button>
</div>
<el-button v-else type="primary" @click="handleEdit(scope)">
编辑
</el-button>
</template>
</el-table-column>
以上这样代码也不算太简单。
然而如果咱们的需要是要切换两个 column 的程序,比方:
\
那应该怎么实现呢, 大略思路就是抽离列配置成为一个 columns 数组, 用 v-for 遍历 columns, 而后在插槽外面做每一列的判断。通過管制数组程序来调整列程序。大略代码思路如下:
残缺的在线 Demo
<el-table-column
v-for="column in columns"
:prop="column.prop"
:label="column.label"
>
<template #default="scope">
<div v-if="column.prop ==='name'">
<el-input
v-if="scope.row._edit"
v-model="scope.row[scope.column.property]"
></el-input>
<span v-else>{{scope.row[scope.column.property] }}</span>
</div>
<div v-if="column.prop ==='tag'">
<el-select
v-if="scope.row._edit"
v-model="scope.row[scope.column.property]"
style="width: 120px"
>
<el-option
v-for="option in tagOptions"
:label="option.label"
:value="option.value"
></el-option>
</el-select>
<el-tag v-else :type="scope.row.tag ===' 家 '?'info':'success'">
{{scope.row.tag}}
</el-tag>
</div>
</template>
</el-table-column>
JS 代码如下:
const columns = ref([
{
prop: 'date',
label: '日期',
},
{
prop: 'name',
label: '姓名',
},
{
prop: 'tag',
label: '标签',
},
]);
const toggleColumnSort = () => {
columns.value = [...columns.value.slice(0, 1),
columns.value[2],
columns.value[1],
...columns.value.slice(3),
];
};
痛点
以上代码能够看出一些问题:
- 判断太多, 而且相互嵌套在一块
- 每一列的配置相互耦合, 不利于前期的保护
- html 代码和 js 代码混合在一起, 不利于书写
ElTableNext
为了解决以上问题, 封装了基于 el-table 的 ElTableNext 组件。
以上的代码用 ElTableNext 能够如下实现:
在线 Demo
<el-table-next :column="column" :data="tableData" />
tsx 代码如下:
const column = ref([
{
prop: 'date',
label: '日期',
},
{
prop: 'name',
label: '姓名',
render: (value, scope) =>
scope.row._edit ? (
<el-input
model-value={value}
onUpdate:modelValue={(val) => {scope.row[scope.column.property] = val;
}}
/>
) : (value),
},
{
prop: 'tag',
label: '标签',
render: (value, scope) =>
scope.row._edit ? (
<el-select
model-value={value}
style='width: 120px'
onUpdate:modelValue={(val) => {scope.row[scope.column.property] = val;
}}
>
{tagOptions.map((option) => (<el-option label={option.label} value={option.value}></el-option>
))}
</el-select>
) : (<el-tag type={scope.row.tag === '家' ? 'info' : 'success'}>
{value}
</el-tag>
),
},
]);
const toggleColumnSort = () => {
column.value = [...column.value.slice(0, 1),
column.value[2],
column.value[1],
...column.value.slice(3),
];
};
设计准则
- 齐全兼容
el-table
的原有相干 API 和事件, 办法等, 保持一致。 - 通过 JSON 来配置列表构造
此外, 减少了一些额定的个性, 提供更好的 typescript 提醒。因而封裝的時候,花了很多功夫去折腾 el-table typescript 类型。比方:
渲染简单列内容提供两种形式:
- 一种是插槽 Slot,
- 一种是 render 函数。render 函数的话须要开始
lang="tsx"
tsx 对于相熟react
开发者来说,会更加亲切。然而也失去 vue template 提供的便当。比方v-model
. 你须要本人在model-value={value}
中设置value
, 在onUpdate:modelValue={(val) => {}}
中扭转 value 值
看下跳转查看如下 Demo:
- render- 形式应用
- slot- 形式应用
源码封装
实质就是利用 tsx 对 el-table 进行封装, 并且提供了一些额定的个性。对 render el-table-column
的時候判断是 slot 还是 render 函数。总代码量包含类型辅助的代码不超过两百分代码 — 代码跳转 github
ElTableNext 别离实现了官网el-table
所有 demo,应该还是比拟稳的。
可跳转查看如下 Demo: https://el-table-next.vercel.app/guide/example.html
Other
喜爱的同学能够间接把源码靠过去放在本人我的项目中, 或者也能够间接 npm 装置. 此外还提供了 PlayGround 给小伙伴游玩
- 组件源码
- 组件文档