vue 關於生命周期
序言:
1. vue 單組件的生命周期;
2. vue 父子組件的生命周期;
3. axios 異步請求 與 vue 的組件周期;
一、vue 每個組件的生命周期
關於每個組件的生命周期,官方文檔裏也提供了,網上也能搜到各路大神們的相關文章,這裏不贅述,貼一個網址以及簡單總結。
Vue的生命周期 - 轉自淺白
簡單總結:
1.beforeCreate 此時 $el、data 的值都為 undefined ;
2.created 此時可以拿到 data 中的值,但是 this.$el 任然是 undefined ;
3.beforeMounte 此時可以打印 this.$el, 但是當中的 {{ data }} 還沒有被替換,this.$el 是虛擬節點;
4.mounted data,$el 均可以被打印,{{ data }} 也已經被替換成正式的 Dom, vue實例被掛載在真實的 dom 樹上;
5.beforeUpdate/updated ;
6.beforeDestroy/destroyed;
一張簡單示意圖:
二、父子組件的生命周期
在項目中,平時可能更多的是關心單個組件的生命周期。
最近手頭的一個項目有一個優化:入口是一個平臺(父系統),在這個父系統中點擊按鈕進入子系統的相應模塊,當然,窗口打開方式是 _blank,父子系統之間的通信流程是,vue路由導航守衛根據 cookie 中的 token 設置,cookie 中如過有 token ,正常跳轉,沒有 token ,通過 H5 postMessage() / window.addEventListener(‘message‘, function(event){}, false) 來
不過問題就出現在 _blank 上(這是技術選型的時候沒有考慮的,vue 比較適合 spa 項目),如果我先以一個賬號信息進入子系統的一個模塊(打開了一個新標簽頁),然後不關閉這個頁面回到父系統的窗口,切換賬號登陸父系統,任然點擊進入同一個子系統的模塊,此時會發現,這次進入時拉取的數據是依據 localStorage 中存放的前一個 userId 拉取的,但是,F5 刷新一下就能拉取正確信息,這就不合理了。
後來閱讀源碼,發現,子系統中最基礎的子組件中某些關鍵信息都是從 localStorage 中獲取,而每個模塊中都有 postMessage 方法,只不過這個方法是在父組件的 mounted 階段才調用,這就是導致了上面的換賬號後進入模塊,子組件根據 localStorage/cookie 中的前賬號信息先去拉取數據,完成初始化,到所有子組件的初始化完成後父組件才執行 mounted 中 postMessage 方法,獲取並在 cookie 中設置後賬號的 token ,然後 F5 刷新時,所用的請求頭中是後賬號的 token,才拉取到正確的數據。
這裏面的父子組件的生命周期是:
1.加載渲染過程:
父 beforeCreate -> 父 created -> 父 beforeMount -> 子 beforeCreate -> 子 created -> 子 beforeMount -> 子 mounted -> 父 mounted
2.子組件更新過程
父 beforeUpdate -> 子 beforeUpdate -> 子 updated -> 父 updated
3.父組件更新過程
父 beforeUpdate -> 父 updated
4.銷毀過程
父 beforeDestroy -> 子 beforeDestroy -> 子 destroyed -> 父 destroyed
明白了父子組件的渲染時間點,那在父組件 beforeCreate / created / beforeMount 時調用 postMessage 方法不就可以了嗎?
答案是不行。為什麽?因為異步。我嘗試了,在 父組件 的上面三個階段內調用 postMessage 方法,其回調函數的執行一定會落後於子組件的渲染掛載,即 子組件憑借 cookie / loaclStorage 裏面的前賬號信息拉取數據 一定會在 後賬號的 token 被存放到 cookie 中之前執行,這是其一;其二,因為 vue 推薦的是 axios 請求模塊,這是一個異步請求模塊,即使在父組件三個階段內去更新用戶信息,這一步依然會落後於子組件的渲染掛載。
那麽如何解決?
我的解決辦法:組件內路由鉤子 beforeRouteEnter(to, from, next)
在這個鉤子中,調用 postMessage,獲取 最新 token, 在其回調函數中,憑借新的 token, 使用 jquery(本來項目中有依賴)發送 一個拉取用戶關鍵信息的 ajax 請求,這個請求設置成同步,獲取到數據後,將相關信息更新到 cookie / localStorage 中,確保後續的請求都是依據最新的用戶信息。在確保上面的操作全部完成之後,next() 到想要的路由上去。
尾聲:
axios 中沒有同步請求,$.ajax 也不推薦使用同步請求。需求如此,尚未找到更好的解決辦法,vue 仍需探索。
vue 關於生命周期