RouteReuseStrategy angular路由複用策略詳解,深度刨析路由複用策略

關於路由複用策略網上的文章很多,大多是講如何實現tab標籤切換歷史數據,至於如何複用的原理講的都比較朦朧,代碼樣例也很難適用各種各樣的路由配置,比如懶加載模式下多級嵌套路由出口網上的大部分代碼都會報錯。
我希望能通過這篇文章把如何複用路由的原理講明白,讓小夥伴能明明白白的實用路由複用策略,文字中有不詳實和錯誤的地方歡迎小夥伴批評指正

對路由複用策略的理解

路由複用策略的是對路由的父級相同節點的組件實例的複用,我們平時看到的多級嵌套路由切換時上層路由出口
的實例並不會從新實例化就是因爲angular默認的路由複用策略在起作用,而我們從寫路由複用策略能實現很多事情,其中之一就是實現
歷史路由狀態(數據)的存儲,即jquery時代的tab頁籤和iframe實現操作歷史的切換。我一開始
認爲路由複用策略就是對歷史路由數據的複用策略,這個錯誤的觀念導致我對路由複用策略接口方法理解起來異常困難,不知小夥伴和我
犯沒犯同樣的錯誤。觀念正確了,下面就理解起來比較方便了,寫路由複用策略也就比較順手了。

下面是angular默認路由複用策略,每切換一下路由,下面代碼都再默默的執行。

export class DefaultRouteReuseStrategy {
    shouldDetach(route) { return false; }
    store(route, detachedTree) { }
    shouldAttach(route) { return false; }
    retrieve(route) { return null; }
    shouldReuseRoute(future, curr) {
        return future.routeConfig === curr.routeConfig;
    }
}

每個活動路由是一棵樹,每個節點都有一個ActivatedRouteSnapshot,root節點是RouterModule.forRoot(Routes)Routes之上的一個默認路由,也無法配置

路由複用策略解析

路由複用策略方法調用順序

  1. shouldReuseRoute(future, curr)
  2. retrieve(route)
  3. shouldDetach(route)
  4. store(route, detachedTree)
  5. shouldAttach(route)
  6. retrieve,取決一上一步的返回值
  7. store(route, detachedTree),取決第五步

shouldReuseRoute

shouldReuseRoute()決定是否複用路由,根據切換的前後路由的節點層級依次調用,
返回值爲true時表示當前節點層級路由複用,然後繼續下一路由節點調用,入參爲切換的下一級路由(子級)的前後路由,
返回值爲false時表示不在複用路由,並且不再繼續調用此方法(當前路由不再複用,其子級路由也不會複用,所以不需要再詢問下去),
root路由節點調用一次,非root路由節點調用兩次這個方法,第一次比較父級節點,第二次比較當前節點,

retrieve

retrieve()接上一步奏,噹噹前層級路由不需要複用的時候,調用一下retrieve方法,其子級路由
也會調用一下retrieve方法,如果返回的是null,那麼當前路由對應的組件會實例化,這種行爲一直持續到末級路由。

shouldDetach

shouldDetach是對上一路由的數據是否實現拆離,其調用開始是當前層級路由不需要複用的時候,即shouldReuseRoute()返回false的時候,
如果這時候反回false,將繼續到上一路由的下一層級調用shouldDetach,直到返回true或者是最末級路由後才結束對shouldDetach
的調用,當返回true時就調用一次store 方法,請看下一步奏

store

store存儲路分離出來的上一路由的數據,當 shouldDetach返回true時調用一次,存儲應該被分離的那一層的路由的DetachedRouteHandle
注意:無論路由樹上多個含有組件component路由節點,能分離出來的只能有一個,被存儲的也只能有一個,感覺這種機制對使用場景有很大限制。

shouldAttach

shouldAttach是對當前路由的數據是否實現恢復(附加回來),其調用開始是當前層級路由不需要複用的時候,即shouldReuseRoute()返回false的時候,
這和shouldDetach的調用時機很像,但是,並不是所有的路由層級都是有組件實例的,只有包含componentroute纔會觸發shouldAttach
如果反回false,將繼續到當前路由的下一帶有component的路由層級調用shouldAttach,直到返回true或者是最末級路由後才結束對shouldAttach
的調用,當返回true時就調用一次retrieve 方法,如果retrieve方法去獲取一下當前路由的DetachedRouteHandle,返回一個DetachedRouteHandle,就再調用一次store,
再保存一下retrieve返回的DetachedRouteHandle。注意注意:無論路由樹上多個含有組件component路由節點,能恢復數據的只能有一個節點,
這和shouldDetach是一個套路,對使用場景有很大限制。

總結·這個還是實驗性的路由複用策略還是不夠強大

路由複用策略這種調用機制對使用場景限制很大 ,比如多級路由出口嵌套就無法實現路由數據緩存。因爲多級路由出口嵌套的應用切換路由時,前後路由會包含
多個帶component的路由節點,而每次對路由的存儲和恢復只能存儲和恢復某一個節點的component的DetachedRouteHandle,其他路由節點上的component就是被從新實例化。
明白這一點後我就放棄了想寫一個可以適用任何場景的路由複用策略的想法,如果有小夥伴能解決好這一業務場景,歡迎賜教。

如果這個路由複用策略可以存儲一個路由上多個節點的DetachedRouteHandle,和恢復多個節點的DetachedRouteHandle,應該能解決上面是的多級路由出口嵌套場景,
但不知道會不會帶來別的問題。

一個路由複用策略用例

下面貼一個路由複用策略用例,應該是滿足大部分人的業務要求,注意事項:只能是末級路由的緩存,且路由切換的時候路由節點上的component不能超過兩個。

import {ActivatedRouteSnapshot, DetachedRouteHandle, Route, RouteReuseStrategy} from "@angular/router";

export class CustomerReuseStrategy implements RouteReuseStrategy {
  static handlers: Map<Route, DetachedRouteHandle> = new Map();
  shouldDetach(route: ActivatedRouteSnapshot): boolean {
    return !route.firstChild;
  }
  shouldAttach(route: ActivatedRouteSnapshot): boolean {
    return !!CustomerReuseStrategy.handlers.has(route.routeConfig);
  }
  shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot) {
    return curr.routeConfig === future.routeConfig;
  }
  retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
    return CustomerReuseStrategy.handlers.get(route.routeConfig);
  }
  store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
    CustomerReuseStrategy.handlers.set(route.routeConfig, handle);
  }
}

很精簡,但是很好用,小夥伴可以根據自己的業務邏輯進行改造。

如果感覺這篇文章對你有幫助,請點個贊吧 👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章