文章目录
相信 element-ui 大家都有所耳闻,table 也是老朋友了,不过在使用它的时候大家是怎么使用的呢?是直接在官网上cv使用吗?这种方式,我相信写起来会有点小难受,反正我感觉要是一共表格就cv一次,对于我来说是有点难受的,但是如果这个 table 表格可以通过一个 json 这种类似的格式进行配置,会不会方便很多呢
配置数据基础分析
-
直接复制官网的案例使用 table 组件,会让我们页面的代码增加不说,还会变得不是那么好维护,每次增加删除或者修改,都需要在结构里面去找,而且这种看起来差不多的配置,肯定是能动态生成的话就动态生成,毕竟都是 "懒人"
-
开头提到过,通过 json 配置生成,那应该怎么确定这个 json 配置呢?我们不妨写看看官网的案例示例代码,如图:
-
可以看到,其实一个列需要的基础属性是 prop 和 label,prop 实现数据的填充,label 就负责表头的显示,所以我们配置的数据,只收应该具备什么,是不是 prop 和 label 呢?所以我们可以写出一个基础的配置数据,如下:
jsconst tableColConfig = [ { prop: 'date', label: '日期' }, { prop: 'name', label: '姓名' }, { prop: 'address', label: '地址' } ]
-
这个数据只是最基础的,后续讲解会继续扩展
封装 el-table-column
-
有了数据之后,我们应该怎么封装,才能通过数据动态生成呢?像这种渲染结构,我们首先想到的必然就是 v-for,也确实如此,所以我们先创建一个 vue 文件来进行封装,如下:
html<template> <el-table :border="border" :data="tableData"> <!-- 通过 tableColConfig 进行循环渲染 --> <el-table-column v-for="item in tableColConfig" :key="item.prop" :prop="item.prop" :label="item.label"></el-table-column> </el-table> </template> <script> export default { props: { // 实际显示的表格数据 tableData: { type: Array, default: () => [] }, // 配置表格的数据 tableColConfig: { type: Array, default: () => [] }, // 是否显示边框 border: { type: Boolean, default: true } } } </script> <style scoped></style>
-
有没有发现我这里多写了一个 border 属性呢,这个属性是来控制 el-table 组件是否展示边框的,有这个配置项的话,那我们的配置文件也需要响应的增加一下,如下:
js// 表格列配置 const tableColConfig = [ { prop: 'date', label: '日期' }, { prop: 'name', label: '姓名' }, { prop: 'address', label: '地址' } ] export default { tableColConfig, border: true }
-
看起来是不是感觉非常简单呢?那封装好了这个组件之后,我们还需要实际的来使用一下,如下:
html<template> <div class="container"> <div class="table-box"> <!-- v-bind 可以批量绑定属性 --> <JcTable :tableData="tableData" v-bind="tableConfig"></JcTable> </div> </div> </template> <script> import JcTable from '@/components/JcTable/index.vue' import tableConfig from '@/config/table.config' export default { components: { JcTable }, data() { return { tableData: [ { date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄' }, { date: '2016-05-04', name: '王小虎', address: '上海市普陀区金沙江路 1517 弄' }, { date: '2016-05-01', name: '王小虎', address: '上海市普陀区金沙江路 1519 弄' }, { date: '2016-05-03', name: '王小虎', address: '上海市普陀区金沙江路 1516 弄' } ], tableConfig } } } </script> <style scoped> .container { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; } .table-box { width: 50%; height: 400px; } </style>
-
关于这个 v-bind 这里不做赘述了,有兴趣的大家可以自行点击跳转到文档查看
-
写了这么多,也到了看一眼效果的时候了,也不能光画饼不给吃是不,如图:
-
当我们进行了一次封装之后,后续使用这个表格组件就变得非常的简单了
使用插槽强化
-
上面实现了一个基础的使用,但是很明显无法满足我们常规的开发需求,这样封装之后,我如果需要再每行加一个按钮呢?或者我需要单独给某一列添加其他dom呢?这些应该怎么解决,比如在官网中的案例效果,如图:
-
这种情况在开发中使用 el-table 是非常常见的,而让一个组件在某个位置可以让我们自由编辑替换,大家想到了什么,是不是插槽呢?就是插槽了,关于插槽这里也不做赘述了,而这么多列,我应该怎么才能让我的内容放入到指定的位置中呢?一一对应不难想到,具名插槽
-
现在我们已经知道可以通过具名插槽来解决这个问题了,应该如何在渲染的列的时候,动态的添加在我们封装的组件中呢?这时候最开始的配置已经无法满足我们的需求了,还需要一个属性 slotName,当配置的数据中,存在 slotName 时,就使用具名插槽,插槽的名字就是 slotName属性的值,修改的数据如下:
jsconst tableColConfig = [ { prop: 'date', label: '日期' }, { prop: 'name', label: '姓名', slotName: 'name' }, { prop: 'address', label: '地址' }, { prop: 'operate', label: '地址', slotName: 'operate' } ]
-
在修改封装的组件前,我们不妨先看看再案例中,是如何修改这部分的,如下:
-
可以看到,通过这种方式,就可以从el-tale组件中获取到该列中每个单元格对应的值,并且可以在这个范围内自定义的书写dom,所以结合插槽,我们就可以写出如下的代码:
html<template> <el-table :border="border" :data="tableData"> <el-table-column v-for="item in tableColConfig" :key="item.prop" :prop="item.prop" :label="item.label"> <!-- 如果存在 slotName 属性,则加入动态插槽 --> <template #default="scope"> <template v-if="item.slotName"> <slot :name="item.slotName" :row="scope.row"></slot> </template> <template v-else> <span>{{ scope.row[item.prop] }}</span> </template> </template> </el-table-column> </el-table> </template> <script> export default { props: { // 实际显示的表格数据 tableData: { type: Array, default: () => [] }, // 配置表格的数据 tableColConfig: { type: Array, default: () => [] }, // 是否显示边框 border: { type: Boolean, default: true } } } </script> <style lang="less" scoped></style>
-
只是增加了一个if判断,还是比较好理解的,那么增加这个之后,我们只需要按照正常使用插槽的方式使用即可,如下:
html<template> <div class="container"> <div class="table-box"> <JcTable :tableData="tableData" v-bind="tableConfig"> <!-- 使用插槽 --> <template #name="{ row }"> <span style="color: #f40">{{ row }}</span> </template> <template #operate> <el-button type="primary">操作</el-button> </template> </JcTable> </div> </div> </template>
-
我们来看看现在显示效果,如图:
-
在页面的显示中,我们已经可以拿到当前行的数据,具体怎么使用,那就是根据业务自己进行实现了
结语
- 使用插槽之后,就已经可以满足日常的基本使用了,如果你还需要其他的需求,可以在此基础上进行扩展
- 比如序列号,勾选状态等等,亦或者和其他组件配合,再次封装为一个组件,通过这种分层的思想,可以解决很多业务的问题