基于 Table 标签的展示数据组件.
Table 组件主要特点在于:
组件 data 的解耦, 减少重复代码;
良好的扩展性, 可以通过自定义列模板来适应不同的业务场景.
1. 实例
代码
- <fat-table :data="tableData">
- <template slot-scope="{ item }">
- <fat-table-column label="姓名">{{ item.name }}</fat-table-column>
- <fat-table-column label="日期">{{ item.date }}</fat-table-column>
- <fat-table-column label="地址">{{ item.address }}</fat-table-column>
- </template>
- </fat-table>
- <!-- 自定义列模板 -->
- <fat-table :data="tableData">
- <template slot-scope="{ item }">
- <fat-table-column label="头像">
- <fat-hover-tip type="right-center">
- <template slot="hover-part">{{ item.name }}</template>
- <template slot="tip-part">
- <img src="/static/img/gakki.jpg" alt="示意图">
- </template>
- </fat-hover-tip>
- </fat-table-column>
- <fat-table-column label="地址">{{ item.address }}</fat-table-column>
- <fat-table-column label="操作">
- <fat-button class="btn" type="primary" size="mini" @click="$message({ content:'编辑'})"> 编辑 </fat-button>
- <fat-button class="btn" type="primary" size="mini" @click="$message({ content:'删除'})"> 删除 </fat-button>
- </fat-table-column>
- </template>
- </fat-table>
实例地址: Table 实例 https://fatge.xyz/blog/juejin-example-3#/Table
代码地址: GitHub UI-Library
2. 原理
Table 组件的基本结构如下
主要可分为两个部分:
表格头 (Table-head): 包裹在 <thead> 标签内, 用于定义了一组定义表格的列头;
表格内容 (Table-body): 包裹在 <tbody> 标签内, 用于定义表格的内容.
首先实现 Table-body, 再依据其对应 label 来生成 Table-head.
Table-body 表格内容:
- <template>
- <table :class="['table-wrapper', {'is-stripe': stripe }]">
- <thead>
- ...
- </thead>
- <!-- Table-body -->
- <tbody class="table-body-wrapper">
- <tr v-for="(item, index) in data" :key="index" :data-index="index" class="tr-wrapper">
- <slot v-bind:item="item"></slot>
- </tr>
- </tbody>
- </table>
- </template>
- <script>
- export default {
- props: {
- data: { type: Array, default: () => [] },
- align: { type: String, default: "left" },
- stripe: { type: Boolean, default: false }
- },
- provide() {
- return {
- fatTable: this
- };
- },
- ...
- };
- </script>
组件的 prop 中包含所需数据 data , 利用 v-for="(item, index) in data" 指令生成每一行 tr, 再通过 slot-scope 来生成每一项的内容, 此时的数据流变为
具体使用时, 只需要利用 slot-scope 来传递这个数据即可
- <fat-table :data="tableData">
- <template slot-scope="{ item }">
- <fat-table-column label="姓名">{{ item.name }}</fat-table-column>
- </template>
- </fat-table>
这样使得每一个 table-column 都可以被自定义, 然后可以拓展成为模板.
Table-head 表格头:
由于每个 fat-table-column 都有 label 属性, 利用这个 prop 来生成 Table-head, 在 Table 组件中 provide 当前组件用于子组件的访问
- provide() {
- return {
- fatTable: this
- };
- }
同时 fat-table-column 组件的实现
- <template>
- <td class="td-wrapper c-size-m">
- <slot > 无 </slot>
- </td>
- </template>
- <script>
- export default {
- props: {
- label: { type: String, required: true }
- },
- inject: ["fatTable"],
- created() {
- this.$nextTick(() => {
- let dom = this.$el.parentNode;
- let index = null;
- while (dom.tagName !== "TR") {
- dom = dom.parentNode;
- }
- index = dom.getAttribute("data-index");
- if (index === "0") {
- this.fatTable.addLabel(this.label);
- this.$destroy = () => {
- this.fatTable.delLabel(this.label);
- };
- }
- });
- }
- };
- </script>
当组件 create 时, 判断是否为第一行, 如果是, 则调用 this.fatTable.addLabel(this.label) , 通知父组件需要添加当前 label 到 Table 组件的 head 中, 同时定义当组件 destroy 时, 删除对应 label.
- this.$destroy = () => {
- this.fatTable.delLabel(this.label);
- };
在 Table 组件中, 定义 addLable 以及 delLabel 的处理方法
- addLabel(label) {
- const { labels } = this;
- const existItem = labels.find(item => item.label === label);
- // 利用 colspan 来处理合并表头的情况
- if (existItem) {
- existItem.colspan += 1;
- } else {
- labels.push({
- label,
- colspan: 1
- });
- }
- },
- delLabel(label) {
- this.labels = this.labels.filter(item => item.label !== label);
- }
3. 结论
利用 vue 提供的一些插槽属性以及 provide , inject 来实现 Table 组件, 虽然功能不够强大, 但是具备良好地可扩展性, 可进一步封装所需组件.
往期文章:
从零实现 Vue 的组件库 (零)- 基本结构以及构建工具
从零实现 Vue 的组件库 (一)- Toast 实现
从零实现 Vue 的组件库 (二)- Slider 实现
从零实现 Vue 的组件库 (三)- Tabs 实现
从零实现 Vue 的组件库 (四)- File-Reader 实现
从零实现 Vue 的组件库 (五)- Breadcrumb 实现
从零实现 Vue 的组件库 (六)- Hover-Tip 实现
从零实现 Vue 的组件库 (七)- Message-Box 实现
从零实现 Vue 的组件库 (八)- Input 实现
从零实现 Vue 的组件库 (九)- InputNumber 实现
从零实现 Vue 的组件库 (十)- Select 实现
从零实现 Vue 的组件库 (十一)- 结合 Functional Component 实现 Date-picker
来源: https://juejin.im/post/5c4aa685518825254e4d48e8