在現有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]);
});
});
},
});
使用
首先需要在ElTabs上使用這個指令
<el-tabs v-tabs-lifecycle> .... <el-tabs>
在某個子元件中
onTabShow(){ //當前元件所屬的標籤被開啟了 }
在模板中
監聽ElTabPane的active事件即可<el-tabs v-tabs-lifecycle> <el-tab-pane @active="onActive"> </el-tab-pane> <el-tabs>
完。