Table 表格組件實現

基於Table標籤的展現數據組件。javascript

Table 組件主要特色在於:
  • 組件 data 的解耦,減小重複代碼;
  • 良好的擴展性,能夠經過自定義列模板來適應不一樣的業務場景。

1. 實例

最終效果

代碼html

<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 實例java

代碼地址:Github UI-Librarygit

2. 原理

Table 組件的基本結構以下github

最終效果

主要可分爲兩個部分:app

  • 表格頭(Table-head):包裹在 <thead> 標籤內,用於定義了一組定義表格的列頭;
  • 表格內容(Table-body):包裹在 <tbody> 標籤內,用於定義表格的內容。

首先實現Table-body,再依據其對應 label 來生成Table-head。dom

Table-body 表格內容ide

<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 來生成每一項的內容,此時的數據流變爲ui

最終效果

具體使用時,只須要利用 slot-scope 來傳遞這個數據便可this

<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) ,通知父組件須要添加當前 labelTable組件的 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 提供的一些插槽屬性以及 provideinject 來實現 Table 組件,雖然功能不夠強大,可是具有良好地可擴展性,可進一步封裝所需組件。

原創聲明: 該文章爲原創文章,轉載請註明出處。

相關文章
相關標籤/搜索