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

結論:javascript

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

  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] );
  } 

  

基礎版java

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

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

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

 

改進版angular2

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

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

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"這一句。

 

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

若是不加藍色框線部分區分,存取不免出現衝突。

 

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

禮尚往來,因爲此文以前也參考了前面的人的改進方案,故傳承改進,但願能幫到你。

相關文章
相關標籤/搜索