web-dev-qa-db-ja.com

Angular2は、レイジーモジュールのロードでカスタム再利用戦略を機能しません

私はangular2プロジェクトで カスタム再利用戦略 を使おうとしましたが、遅延モジュールの読み込みでは機能しないことがわかりました。これを知っている人はいますか?私のプロジェクトはangular 2.6.4

再利用-strategy.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の値は保持されません。

まだサポートされていないのかわかりません。助けてくれてありがとう。

16
Seungwon

RouteReuseStrategyはLazyLoadedコンポーネントで機能します。

ここでの問題は、ハンドルを保存および取得するためのキーとしてroute.routeConfig.pathを使用していることです。

理由はわかりませんが、LazyLoadedモジュールでは、shouldAttachを実行するとroute.routeConfig.pathが空になります。

私が使用する解決策は、次のようにルートにカスタムキーを定義することです。

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

このキー値は、次のようにActivatedRouteSnapshotで簡単にアクセスできます。

route.data.key

このキーを使用すると、ハンドルを正しく保存および取得できます。

12
Gauss

これを使用してください。ハンドルを格納および取得するためのキーとしてコンポーネント名を使用します。

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

}

このReuseStrategyを使用する

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

}
1
hanky_panky666

このカスタムの再利用戦略ファイルをレイジーモジュールのロードに使用します

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

}
1
narayan reddy

それを機能させるには、ほとんどの記事が示唆しているように、単純な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;
}
1
Eduard