【 vue / uniapp 】延遲加載數據的特殊處理


在用vue實現一個無限層級的樹型結構時,遇到了這個問題。

頁面結構如圖:

其中,父頁面的處理邏輯:

步驟一:引用並掛載組件,同時向組件props傳遞樹型JSON列表數據(this.list),當然這時候的 this.list 還只是一個空數組。

步驟二:在 onload 事件中從服務器獲取樹型JSON數據並回寫到 this.list,同時這個 this.list 也會自動通過 props 傳遞給組件。

 

當時考慮到對數據的解耦,不想在父頁面中對數據進行過多的處理,拿到服務端的JSON后直接交給組件,剩下的都在組件里實現。

所以對於組件來說,就要對 props 中接收到的數據進一步處理,用來滿足樹型的相關要求。

首先,為了實現對樹型節點的展開/閉合操作,每個節點的數據對象都需要增加一個屬性(opened),用來記憶節點的狀態,同時自動渲染到Dom。

 

組件的處理邏輯:

步驟一:接收 props 中的 list 數據;

步驟二:在組件的 mounted 事件中遍歷 list 中當前層級的節點列表數據對象,增加並初始化屬性 item.opened = false,即默認閉合節點。

步驟三:如果存在子節點,則遞歸引用並掛載組件,同時將子節點列表數傳遞給組件,實現無限層級的樹型渲染。

 

注意:步驟二中為節點數據對象增加 opened 屬性需要使用 this.$set 函數,否則新增加的屬性將不支持與視圖的自動響應。

 

按照以上方式完成之后,發現第一層節點的 opened 屬性並沒有自動響應,通過調試發現組件的 mounted 事件只處理了第一次掛載時接收到的空數組,之后父頁面傳過來的真實數據壓根沒經過處理。

想了一下,才反應過來,因為父頁面在創建時就已經觸發了組件的 mounted 事件;

后來從服務端返回JSON后,修改 props 時不會再次觸發組件的 mounted 事件,反而會觸發 updated 事件,所以才造成了新增屬性無效的情況。

 

弄明白了問題所在,解決起來也很糾結,因為只有第一層組件的數據傳入是異步的,需要從 updated 事件進行處理;

而更下層的組件都是掛載時就會傳入的,還需要從 mounted 進行處理。

另一個問題就是,每次點擊節點時要修改 opened 屬性,而這時也會觸發 updated 事件,所以初始化操作還是不能在 updated 中處理。

 

想明白了問題所在,就嘗試通過 this.$refs 來實現,在父頁面引用組件時,默認先不通過 props 傳入 list 數據,而是在獲取服務端JSON之后,使用 this.$refs.comp.treeRoot(list) 向組件傳入,而組件本身的 mounted 事件用來處理第二層之后的組件數據初始化。

后來又嘗試用 watch 來解決,感覺比 ref 要簡潔一些,核心代碼如下:

watch: {
    list: {
        handler(newVal, oldVal){
            if(kit.isEmpty(oldVal) || oldVal.length === 0){
                this.opened = this.currentLevel < this.openLevel;
                let list = JSON.parse(JSON.stringify(newVal));
                list.forEach((item, i) => {
                    item[this.attrOpened] = this.opened;
                })
                this.treeList = list;
            }
        },
        immediate: true
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM