Angular6路由復用與延遲加載的沖突解決——看看有備無患


結論:

  結論放最上面,送給匆匆查資料的你:

  1.  同時使用延遲加載 + 路由復用,一定不能使用route.routeConfig.path做key去緩存,否則會死得難看。
  2. 經實測(我沒有完全去解讀源代碼),將緩存的key改為下面的函數計算可行。
  private getRouteUrl(route: ActivatedRouteSnapshot) {
    return route['_routerState'].url.replace(/\//g, '_')
      + '_' + (route.routeConfig.loadChildren || route.routeConfig.component.toString().split('(')[0].split(' ')[1] );
  } 

  

基礎版

關於angular2開始的路由復用網上教程很多,例如: https://www.softwarearchitekt.at/post/2016/12/02/sticky-routes-in-angular-2-3-with-routereusestrategy.aspx。

這個最初級的版本有一個問題:在延遲加載模式下,以route.couteConfig.path去做為緩存key是不可取的。經調試,path指的是配置在路由中的路由規則,不同模塊有相同規則的機率相當在,比如每個模塊可能都有 ' ' 做默認路由

(這個版本挺有意思的,當時坑了我很久:從一個模塊的默認路由跳到另一模塊默認路由,由於path都是‘’,所以直接從緩存中把前一模塊原來的緩存取了出來,導致看到的效果就是點了routerLink跳轉沒反應,也不報錯。因為之前使用routerLink時記得要添加模塊引用。好長時間,我以為是routerLink沒有配置好,或者angular6升級了什么被遺漏了。根本就沒有往路由上想!) 

 

改進版

參考:https://www.cnblogs.com/lovesangel/p/7853364.html

這個版本意識到了上面的問題,采用用路由的url做路徑,其實問題依然沒解決,經調試還是會出現問題:

Uncaught Error: Uncaught (in promise): Error: Cannot reattach ActivatedRouteSnapshot created from a different route
Error: Cannot reattach ActivatedRouteSnapshot created from a different route
at setFutureSnapshotsOfActivatedRoutes (router.js:2267)
at createNode (router.js:2255)
at router.js:2294
at Array.map (<anonymous>)
at createOrReuseChildren (router.js:2278)
at createNode (router.js:2247)
at createRouterState (router.js:2239)
at MapSubscriber.project (router.js:4038)
at MapSubscriber.push../node_modules/rxjs/_esm5/internal/operators/map.js.MapSubscriber._next (map.js:75)
at MapSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next (Subscriber.js:93)
at setFutureSnapshotsOfActivatedRoutes (router.js:2267)

在參考了https://stackoverflow.com/questions/41584664/error-cannot-reattach-activatedroutesnapshot-created-from-a-different-route后,在retrive時加上

if (route.routeConfig.loadChildren) return null;

依然不能解決問題,基本調試如下:

 

這引起了我的注意,因為這兩個組件的路由參數是一樣的:

      path: '', component: ProjectDisplayComponent,
      children: [
        {
          path: '', component: ProjectHomeComponent
        },

shouldAttach方法也進了兩次:

路由要復用,兩個組件肯定都要進緩存的,用同樣的key肯定會出問題的,於是在改進版上做修改如下:

  private getRouteUrl(route: ActivatedRouteSnapshot) {
    return route['_routerState'].url.replace(/\//g, '_')
      + '_' + (route.routeConfig.loadChildren || route.routeConfig.component.toString().split('(')[0].split(' ')[1] );
  }  

后面多出的一行代碼:用於區分延遲加載時的模塊路徑,以及默認子組件與父組件。至此,問題解決(而且,可以去除 "if (route.routeConfig.loadChildren) return null"這一句。

 

 經過測試:的確默認子組件及父組件都有緩存:

如果不加藍色框線部分區分,存取難免出現沖突。

 

————————————————————————————————————————————————————————————————

禮尚往來,由於此文之前也參考了前面的人的改進方案,故傳承改進,希望能幫到你。

 


免責聲明!

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



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