1. 程式人生 > >vue 關於生命周期

vue 關於生命周期

如何 節點 鉤子 請求 調用 新標簽頁 logs pos 依賴

序言:

  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) 來

向父系統獲取 toke, 在回調函數 function(event){} 中,將獲取的token 首先放入 cookie 中,這樣,下次 axios 請求時可以從 cookie 中取值並設置請求頭,其他用戶信息等在依此根據 token 去獲取並存入 localStorage 中。

  不過問題就出現在 _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 關於生命周期