基于 Element-plus Table 封装的易用, 统一, 敌对的 Vue Table 组件

  1. 组件源码
  2. 组件文档
  3. 原文

    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),  ];};

设计准则

  1. 齐全兼容el-table 的原有相干 API 和事件, 办法等, 保持一致。
  2. 通过 JSON 来配置列表构造

此外, 减少了一些额定的个性, 提供更好的 typescript 提醒。因而封裝的時候,花了很多功夫去折腾 el-table typescript 类型。比方:


  1. 渲染简单列内容提供两种形式:
  • 一种是插槽 Slot,
  • 一种是 render 函数。render 函数的话须要开始lang="tsx" tsx 对于相熟react开发者来说,会更加亲切。然而也失去 vue template 提供的便当。比方v-model. 你须要本人在model-value={value}中设置value, 在onUpdate:modelValue={(val) => {}}中扭转 value 值

看下跳转查看如下 Demo:

  1. render-形式应用
  2. 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 给小伙伴游玩

  1. 组件源码
  2. 组件文档