angular4 路由重用策略 RouterReuseStrategy


單頁面應用現在是主流,隨之而來的缺點:頁面間切換時不能保存狀態

angular4出了一個RouteReuseStrategy路由重用策略可以讓組件所有的state和渲染好的html存起來,然后在切回去的時候再調出來。

export declare abstract class RouteReuseStrategy{
   abstract shouldReuseRoute():Boolean
   abstract shouldAttach():Boolean
   abstract retrieve():DetachedRouteHandle | null
   abstract shouldDetach():Boolean
   abstract store():void
}

替換一旦發生,某些組件將被丟棄

這時shouldDetech,store將被調用,用於緩存即將被丟棄的組件

有組件丟棄,自然有組件替補進來

這時shouldAttach retreive將被調用,用於調出緩存的組件

🌊 應用場景

1.進入某個路由頁面,進行操作,切換頁面再返回,能還原到之前的操作狀態;

2.切換右邊的tab,能進入到對應的路由頁面(操作后的狀態);

3.點擊右邊tab里的關閉按鈕或頁面上的關閉按鈕,刪除某個路由頁面的快照,再次點開這個路由頁面,頁面恢復初始狀態;

 

🌊 下面是具體實現

要注意的點:

1. store方法:存儲上一個頁面的快照

2.關閉路由有幾種情況:

    i 打開A頁面后 打開B頁面 關閉B頁面(此時B頁面沒有快照) -> 觸發store方法

    ii 打開A頁面后 打開B頁面 關閉A頁面 (此時A頁面有快照)   -> 不觸發store方法

  iii 打開A頁面后 打開B頁面 回到A頁面 關閉A頁面 (此時A頁面有快照) ->不觸發store方法

    iii 打開A頁面后 打開B頁面 回到A頁面 關閉B頁面 (此時B頁面有快照) ->不觸發store方法

   因此頁面在沒有快照的時候關閉  需要在store方法里做一個暫緩刪除的操作(先記錄key 進去新頁面后 再刪除key)

   這樣頁面的ngOnDestroy()方法才能執行  才能避免事件重復監聽(在ngOnDestroy()中執行)

相關的知識點:

ActivatedRouteSnapshot:包含當前插座中加載組件某一特定時間路由信息

RouteReuseStrategy:路由復用策略

DetachedRouteHandle:組件當前所有狀態(路由快照

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

export class ExtensionRouteReuseStrategy implements RouteReuseStrategy {
  private static waitDelete:string;
  public static storedRoutes: Map<string, DetachedRouteHandle> = new Map<string, DetachedRouteHandle>();

  constructor(){
    //關閉操作(右上角或者history頁面)
    this.storageNotifyRouter.destoryTopic.subscribe((key) => {
      this.processDestory(key);
    });
 };


 //是否緩存【離開路由時觸發】
  shouldDetach(route: ActivatedRouteSnapshot): boolean {
    if (route.data && route.data.key) {
      return true;
    }
    return false;
  }

  //緩存組件【離開路由時觸發】
  store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
    const key = this.findStoreKey(route);
    const key$$ = this.lastClosedKey + _SPLIT;
    //未存儲快照的情況下 跳轉新頁面 再刪key
    if (this.waitDeleteRoutes.size > 0) {
      const array = Array.from(this.waitDeleteRoutes.keys());
      for (const deletekey of array) {
        if (deletekey == key) {
          const oldHandle = handle as { componentRef: ComponentRef<any> };
          oldHandle.componentRef.destroy();
        }
        this.waitDeleteRoutes.delete(deletekey);
      }
      return;
    }
    //存儲上一個頁面快照 進入新頁面
    if (handle && !(key === this.lastClosedKey || key.startsWith(key$$))) {
      this.lastClosedKey = '';
      this.storedRoutes.set(key, handle);
    }
  }

 //是否還原【進入路由時觸發】
  shouldAttach(route: ActivatedRouteSnapshot): boolean {
    const key = this.findRetrieveKey(route);
    const result: boolean = !!key && !!this.storedRoutes.get(key);
    return result;
  }

  //還原路由【進入路由時觸發】
  retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
    const key = this.findRetrieveKey(route);
    let handle = null;
    if (key && this.storedRoutes.get(key)) {
      handle = this.storedRoutes.get(key);
      this.routerNotifyStorage.notifyRetrieve(key);
    }
    return handle;
  }

 //是否復用路由【進入路由時觸發】
  shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
    const result: boolean = future.routeConfig === curr.routeConfig;
    return result;
  }

  findStoreKey(route: ActivatedRouteSnapshot): string {
    let key = "";
    if (route.data && route.data.key) {
      if (route.children[0] && route.children[0].data && route.children[0].data.key) {
        this.findStoreKey(route.children[0]);
      } else {
        key = route.data.key;
      }
    }
    return key;
  }

  findRetrieveKey(route: ActivatedRouteSnapshot): string {
    let key = "";
    if (route.data && route.data.key) {
      key = route.data.key;
    }
    return key;
  }

  processDestory(key: string, waiteDelete: boolean = true) {
    this.lastClosedKey = key;
    let existKey: boolean = false;
    const array: string[] = Array.from(this.storedRoutes.keys());
    for (const keyStored of array) {
      const key$$ = key + _SPLIT;
      //存儲快照的情況下 刪除快照
      if (key === keyStored || keyStored.startsWith(key$$)) {
        const oldHandle = this.storedRoutes.get(keyStored) as { componentRef: ComponentRef<any> };
        oldHandle.componentRef.destroy();
        this.storedRoutes.delete(keyStored);
        existKey = true;
      }
    }
    //未存儲快照 先存當前頁面key
    if (!existKey && waiteDelete) {
      this.waitDeleteRoutes.add(key);
    }
  }
 
}

 

  

 

🌊 后續

保存快照

在離開路由時保存上一個頁面快照,並emit一個事件給左邊的菜單組件和右邊的tab組件,告訴它們路由路徑已改變,同時把新的路由路徑作為參數傳過去

然后在左邊的菜單組件和右邊的tab組件里subscribe事件里去監聽變化,替換新的路由路徑。

這樣在點擊它們的時候就會重定向到新的路由路徑,而快照已保存。

 

刪除快照

點擊右邊tab組件里的關閉按鈕或者點擊頁面上的關閉按鈕時,emit一個刪除快照的事件,同時把路由路徑作為參數傳過去

然后在路由復用策略的ts文件中的subscribe事件里去監聽這個事件,然后執行對應路由的processDestroy()方法

  

 


免責聲明!

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



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