為ElementUI的標籤頁新增生命週期

OLong發表於2021-10-26

在現有ElementUI下,子元件是不知道自己所屬的標籤頁是否處於開啟狀態的。
下面寫一個Vue的指令讓子元件知道

實現

請看逐行註釋。


 type TabPaneChildren = {
    onTabShow?: () => unknown;
    $children: TabPaneChildren[];
  };

  /**
   * 呼叫所有子孫元件的 onTabShow方法
   *
   */
  function callOnShow(instances: TabPaneChildren[]) {
    //遍歷子元件
    instances.forEach((ins) => {
        //如果當前元件有onTabShow方法,則呼叫。
      ins.onTabShow && ins.onTabShow();
       //對當前元件的子元件遞迴呼叫callOnShow。
      if (ins.$children.length > 0) {
        callOnShow(ins.$children);
      }
    });
  }

  Vue.directive("tabs-lifecycle", {
    inserted(_el, _binding, vnode) {
      // 獲取需要新增生命週期方法的ElTabs的例項
      const ins: any = vnode.componentInstance;
      // 獲取所有ELPane的例項
      const panes: any[] = ins.$children.filter((k: any) => k.$vnode.tag?.includes("ElTabPane")) ??
        [];
      // 監聽ElTabs的tab-click事件。詳見官網文件。
      ins.$on("tab-click", async () => {
        // Promise.resolve()的效果等於 Vue.$nextTick();
        // 這一行也可改成ins.$nextTick();
        await Promise.resolve();
        // 遍歷ElPane例項
        panes.forEach((pane) => {
            // 看原始碼可知ElPane的active屬性代表當前ElPane是否被開啟了
            // 從Vue devtool中也可以得知這一點。
          if (!pane.active) return;
            // 從pane的例項上丟擲一個啟用事件。可以直接在模板中監聽
          pane.$emit("active");
            // 呼叫callOnShow方法,該方法會遞迴pane的所有的子孫元件,並呼叫他們的onTabShow方法,如果有的話。
          callOnShow([pane]);
        });
      });
    },
  });

使用

  1. 首先需要在ElTabs上使用這個指令

    <el-tabs v-tabs-lifecycle>
    ....
    <el-tabs>
  2. 在某個子元件中

    onTabShow(){
     //當前元件所屬的標籤被開啟了
    }
  3. 在模板中
    監聽ElTabPane的active事件即可

    <el-tabs v-tabs-lifecycle>
        <el-tab-pane @active="onActive">
        </el-tab-pane>
    <el-tabs>

    完。

相關文章