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

     经过测试:的确默认子组件及父组件都有缓存:

    如果不加蓝色框线部分区分,存取难免出现冲突。

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

    礼尚往来,由于此文之前也参考了前面的人的改进方案,故传承改进,希望能帮到你。

  • 相关阅读:
    Factory——工厂方法
    Subsets II
    【算法设计】快速计算积分图
    Win8驱动的兼容性问题
    Matplotlib快速上手
    Pandas —— (8)数据读取
    Pandas —— (7)数据分组
    Pandas —— (6)多个DataFrame的合并、连接、去重、替换
    Pandas —— (4)常用数学、统计方法
    Pandas —— (3)数据查看、转置、添加、修改、删除、运算(对齐)、排序
  • 原文地址:https://www.cnblogs.com/caption/p/9332393.html
Copyright © 2020-2023  润新知