通過(guò)繼承實(shí)現(xiàn)el-table-column列寬根據(jù)內(nèi)容自適應(yīng)

安裝

已封裝到npm, 可直接安裝使用:

$ npm install ex-table-column --save
$ yarn add ex-table-column

github地址:
https://github.com/mnm1001/ex-table-column

需求

項(xiàng)目中使用element-uiel-tableel-table-column,
需求上需要實(shí)現(xiàn)列寬根據(jù)內(nèi)容自適應(yīng).

實(shí)現(xiàn)方案

element-ui 的table組件本身有著強(qiáng)大的功能, 所以我們期望保留其現(xiàn)有功能, 然后進(jìn)行擴(kuò)展. 基于這樣的前提, 繼承el-table-column組件進(jìn)行擴(kuò)展是一個(gè)比較合適的方案.

Vue組件繼承

vue 提供 extends 以擴(kuò)展已有組件, 所以我們很容易實(shí)現(xiàn)一個(gè)擴(kuò)展于 el-table-column 的組件 ex-table-column:

import { TableColumn } from 'element-ui';

export default {
  name: 'ExTableColumn',
  extends: TableColumn, // 指定繼承組件
};

介入el-table-columnwidth計(jì)算

element-uitable-column.js 源碼中, 我們發(fā)現(xiàn)以下一些內(nèi)容和width計(jì)算有關(guān).

  computed: {
    realWidth() {
      return parseWidth(this.width);
    },

    realMinWidth() {
      return parseMinWidth(this.minWidth);
    },
  },
  methods: {
    setColumnWidth(column) {
      if (this.realWidth) {
        column.width = this.realWidth;
      }
      if (this.realMinWidth) {
        column.minWidth = this.realMinWidth;
      }
      if (!column.minWidth) {
        column.minWidth = 80;
      }
      column.realWidth = column.width === undefined ? column.minWidth : column.width;
      return column;
    },
  },
  created() {
    const chains = compose(this.setColumnRenders, this.setColumnWidth, this.setColumnForcedProps);
    column = chains(column);

    this.columnConfig = column;
  },

我們的實(shí)現(xiàn)思路是Table先渲染, 計(jì)算當(dāng)列內(nèi)容的寬度中的最大值, 再將最大值賦予列寬然后刷新. 所以:

  • 無(wú)法在created中介入, 因?yàn)榇藭r(shí)Table還沒(méi)有mouted,
  • 若在methods中介入的話, 我們還需要手動(dòng)刷新一次組件以觸發(fā)新的width, 也不合適,
  • 所以修改computed是相對(duì)合適的, 因?yàn)?code>computed所依賴(lài)的值發(fā)生變化以后會(huì)自動(dòng)觸發(fā)組件的更新.

計(jì)算內(nèi)容寬度并更新列寬

Table組件mounted后遍歷當(dāng)列內(nèi)容, 獲取最大值. 然后將此值存入dataautoWidth中, 并使autoWidth介入到realMinWidthcomputed計(jì)算中, 這樣就簡(jiǎn)單的實(shí)現(xiàn)了自動(dòng)列寬的功能.

  data() {
    return {
      autoWidth: 0,
    };
  },
  computed: {
    realMinWidth() {
      return this.autoWidth;
    },
  },
  mounted() {
    let cells = window.document.querySelectorAll(`td.${this.columnId} .cell`);
    const autoMinWidth = max(map(cells, item => item.getBoundingClientRect().width));
    this.autoWidth = autoMinWidth;
  },

完善

至此我們已基本實(shí)現(xiàn)自動(dòng)列寬功能, 然而還有一些問(wèn)題需要完善:

兼容

我們其實(shí)期望不去改變el-table-column的原有特性, 而這里直接覆蓋realMinWidth的值稍顯粗暴, 所以我們可以通過(guò)傳入一個(gè)名為autoFixprop來(lái)決定是否啟用自動(dòng)內(nèi)容列寬功能, 若autoFixfalse, 則保留el-table-column原有的realMinWidth計(jì)算邏輯:

props: {
    autoFit: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      autoWidth: 0,
    };
  },
  computed: {
    realMinWidth() {
      if (this.autoFit) {
        return parseMinWidth(max([this.minWidth, this.autoWidth]));
      }
      return parseMinWidth(this.minWidth);
    },
  },
靈活性

el-table-column有復(fù)雜的solt內(nèi)容, 我們可能期望指定某一個(gè)element來(lái)計(jì)算列寬, 所以可以傳入一個(gè)fitByClass的屬性來(lái)指定計(jì)算列寬所依賴(lài)的element:

  props: {
    fitByClass: {
      type: String,
      default: 'cell',
    },
  },
  mounted() {
    let cells = window.document.querySelectorAll(`td.${this.columnId} .${this.fitByClass}`);
    if (isEmpty(cells)) {
      cells = window.document.querySelectorAll(`td.${this.columnId} .cell`);
    }
    const autoMinWidth = max(map(cells, item => item.getBoundingClientRect().width));
    this.autoWidth = autoMinWidth;
  },
分頁(yè)更新

當(dāng)Table帶有分頁(yè)時(shí), 切換分頁(yè)不會(huì)重新觸發(fā)mounted, 但Table的列內(nèi)容的最大寬度可能需要重新計(jì)算, 所以需要在updated中重新計(jì)算autoWidth:

  methods: {
    updateAutoWidth() {
      let cells = window.document.querySelectorAll(`td.${this.columnId} .${this.fitByClass}`);
      if (isEmpty(cells)) {
        cells = window.document.querySelectorAll(`td.${this.columnId} .cell`);
      }

      const autoMinWidth = max(map(cells, item => item.getBoundingClientRect().width));
      if (this.autoWidth !== autoMinWidth) {
        this.autoWidth = autoMinWidth;
      }
    },
  },
  updated() {
    this.updateAutoWidth();
  },
  mounted() {
    this.updateAutoWidth
  },

最后

中間代碼有所精簡(jiǎn), 完整源碼可以參考 ExTableColumn.js .
已封裝到npm, 可通過(guò)npm install ex-table-column --save安裝使用.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容