【问题标题】:Angular2 doesn't work Custom Reuse Strategy with Lazy module loadingAngular2 无法使用延迟模块加载的自定义重用策略
【发布时间】:2017-07-12 00:48:12
【问题描述】:

我尝试在我的 angular2 项目中使用custom reuse strategy, 但我发现它不适用于 延迟模块加载。 有谁知道这件事吗?我的项目是 angular 2.6.4

重用策略.ts

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

export class CustomReuseStrategy implements RouteReuseStrategy {

    handlers: {[key: string]: DetachedRouteHandle} = {};

    shouldDetach(route: ActivatedRouteSnapshot): boolean {
        console.debug('CustomReuseStrategy:shouldDetach', route);
        return true;
    }

    store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
        console.debug('CustomReuseStrategy:store', route, handle);
        this.handlers[route.routeConfig.path] = handle;
    }

    shouldAttach(route: ActivatedRouteSnapshot): boolean {
        console.debug('CustomReuseStrategy:shouldAttach', route);
        return !!route.routeConfig && !!this.handlers[route.routeConfig.path];
    }

    retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
        console.debug('CustomReuseStrategy:retrieve', route);
        if (!route.routeConfig) return null;
        return this.handlers[route.routeConfig.path];
    }

    shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
        console.debug('CustomReuseStrategy:shouldReuseRoute', future, curr);
        return future.routeConfig === curr.routeConfig;
    }

}

app.module.ts

const appRoutes: Routes = [
  { path: 'crisis-center', component: CrisisListComponent },
  { path: 'heroes', loadChildren: 'app/hero-list.module#HeroListModule' },
  { path: '',   redirectTo: '/crisis-center', pathMatch: 'full' }
];
@NgModule({
  imports: [ ... ],
  declarations: [ ... ],
  providers:[
    {provide: RouteReuseStrategy, useClass: CustomReuseStrategy}
  ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }

然后我将<input> 放入两个组件并对其进行了测试。

CrisisListComponent 中的输入值被存储,但HeroListComponent lazy-loaded 的值没有被保留。

我不知道它还不支持。 谢谢你帮助我。

【问题讨论】:

    标签: angular routes lazy-loading reusability


    【解决方案1】:

    RouteReuseStrategy 确实适用于 LazyLoaded 组件。

    这里的问题是您使用route.routeConfig.path 作为存储和检索句柄的密钥。

    我不知道为什么,但是对于 LazyLoaded 模块,在执行 shouldAttach 时,route.routeConfig.path 是空的

    我使用的解决方案是在我的路由中定义一个自定义键,例如:

    { path: '...', loadChildren: '...module#...Module', data: { key: 'custom_key' } }
    

    这个键值在ActivatedRouteSnapshot中可以很方便的访问,比如:

    route.data.key
    

    使用此密钥,您可以正确存储和检索句柄。

    【讨论】:

      【解决方案2】:

      使用这个。它使用组件名称作为键来存储和检索句柄。

      import {ActivatedRouteSnapshot, DetachedRouteHandle, RouteReuseStrategy} from '@angular/router';
      
      export class CustomReuseStrategy implements RouteReuseStrategy {
      
      
        handlers: { [key: string]: DetachedRouteHandle } = {};
      
      
        shouldDetach(route: ActivatedRouteSnapshot): boolean {
          return true;
        }
      
        store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
          this.handlers[this.getKey(route)] = handle;
        }
      
        shouldAttach(route: ActivatedRouteSnapshot): boolean {
          return !!route.routeConfig && !!this.handlers[this.getKey(route)];
        }
      
        retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
          if (!route.routeConfig) {
            return null;
          }
          return this.handlers[this.getKey(route)];
        }
      
        shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
          return curr.routeConfig === future.routeConfig;
        }
      
        private getKey(route: ActivatedRouteSnapshot) {
          let key: string;
          if (route.component) {
            key = route.component['name'];
          } else {
            key = route.firstChild.component['name'];
          }
          return key;
        }
      
      }
      

      【讨论】:

        【解决方案3】:

        要使其正常工作,您应该考虑完整路径,而不是大多数文章建议的简单 route.routeConfig.path。例如:

        private getKey(route: ActivatedRouteSnapshot): string {
            return route.pathFromRoot
                .map((el: ActivatedRouteSnapshot) => el.routeConfig ? el.routeConfig.path : '')
                .filter(str => str.length > 0)
                .join('');
        }
        
        store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
            this.handlers[this.getKey(route)] = handle;
        }
        

        【讨论】:

          【解决方案4】:

          使用这个重用策略

          import { ActivatedRouteSnapshot, DetachedRouteHandle, RouteReuseStrategy } from '@angular/router';
          export class CustomReuseStrategy implements RouteReuseStrategy {
          
            private handlers: {[key: string]: DetachedRouteHandle} = {};
          
          
            constructor() {
          
            }
          
            shouldDetach(route: ActivatedRouteSnapshot): boolean {
              return true;
            }
          
            store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
              this.handlers[route.url.join("/") || route.parent.url.join("/")] = handle;
            }
          
            shouldAttach(route: ActivatedRouteSnapshot): boolean {
              return !!this.handlers[route.url.join("/") || route.parent.url.join("/")];
            }
          
            retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
              return this.handlers[route.url.join("/") || route.parent.url.join("/")];
            }
          
            shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
              return future.routeConfig === curr.routeConfig;
            }
          
          }
          

          【讨论】:

          • 它也适用于延迟加载的子路由,谢谢!
          • 它不会在注销时清除处理程序,我会在主页上获得“/dashboard”路由的快照。有没有办法解决这个问题?
          • @VIshalJain,没有看到你的路由结构,很难诊断出发生了什么。您的应用程序中是否有多个“/dashboard”子路径?这是我在上面的代码中看到的一个潜在陷阱。至于注销时清除的处理程序(DetachedRouteHandle s):从路由器您可以访问路由重用策略,您可以将其转换为自定义重用策略的类型并调用您添加的方法来清除处理程序数组期间登出。由于句柄是不透明的,不确定如何强制 ngOnDestroy()。我的建议:在注销结束时执行浏览器刷新。
          • 其实我自己简单地尝试了这个策略,它似乎有存储句柄的危险 ` //lazy-routing.module.ts ... { path: '', component: LazyComponent, } ` 在与路由树 // app-routing.module.ts ... { path: 'lazy_route', loadChildren: 'app/+lazy/lazy.module#LazyModule', } 中的父级相同的键下,这会导致 Error: Cannot reattach ActivatedRouteSnapshot created from a different route,我认为 OP 和未来的读者希望避免这种情况。其他人可以确认吗?
          【解决方案5】:

          使用此自定义重用策略文件进行延迟模块加载

          import { ActivatedRouteSnapshot, RouteReuseStrategy, DetachedRouteHandle } from '@angular/router';
          
          /** Interface for object which can store both:
           * An ActivatedRouteSnapshot, which is useful for determining whether or not you should attach a route (see this.shouldAttach)
           * A DetachedRouteHandle, which is offered up by this.retrieve, in the case that you do want to attach the stored route
           */
          interface RouteStorageObject {
              snapshot: ActivatedRouteSnapshot;
              handle: DetachedRouteHandle;
          }
          
          export class CustomReuseStrategy implements RouteReuseStrategy {
          
              handlers: {[key: string]: DetachedRouteHandle} = {};
          
              shouldDetach(route: ActivatedRouteSnapshot): boolean {
                  console.debug('CustomReuseStrategy:shouldDetach', route);
                  return !!route.data && !!(route.data as any).shouldDetach;
              }
          
              store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
                  console.debug('CustomReuseStrategy:store', route, handle);
                  this.handlers[route.data['key']]= handle;
              }
          
              shouldAttach(route: ActivatedRouteSnapshot): boolean {
                  console.debug('CustomReuseStrategy:shouldAttach', route);
                  return !!route.data && !!this.handlers[route.data['key']];
              }
          
              retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
                  console.debug('CustomReuseStrategy:retrieve', route);
                  if (!route.data) return null;
                  return this.handlers[route.data['key']];
              }
          
              shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
                  console.debug('CustomReuseStrategy:shouldReuseRoute', future, curr);
                  return future.data === curr.data;
              }
          
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-08-21
            • 1970-01-01
            • 2017-02-22
            • 1970-01-01
            • 2017-03-16
            • 2017-09-03
            • 2019-07-05
            • 1970-01-01
            相关资源
            最近更新 更多