如何在 Angular 2 中为特定路线实施 RouteReuseStrategy shouldDetach

IT技术 javascript angular typescript angular-router
2021-02-08 01:15:09

我有一个 Angular 2 module,我在其中实现了路由,并希望在导航时存储状态。
用户应该能够:

  1. 使用“搜索公式”搜索文档
  2. 导航到结果之一
  3. 导航回“搜索结果” - 无需与服务器通信

这是可能的,包括RouteReuseStrategy.
问题是:
如何实现不应该存储文档?

所以应该存储路由路径“documents”的状态,而不应该存储路由路径“documents/:id”'状态?

6个回答

嘿安德斯,好问题!

我有几乎和你一样的用例,并且想做同样的事情!用户搜索 > 获取结果 > 用户导航到结果 > 用户导航返回 > BOOM 快速返回结果,但您不想存储用户导航到的特定结果。

tl;博士

您需要有一个RouteReuseStrategyngModule. 如果要修改路由存储的时候,修改shouldDetach函数。当它返回时true,Angular 会存储路由。如果要在附加路由时进行修改,请修改该shouldAttach功能。shouldAttach返回 true 时,Angular 将使用存储的路由代替请求的路由。这是一个供您玩耍Plunker

关于 RouteReuseStrategy

通过问这个问题,您已经了解 RouteReuseStrategy 允许您告诉 Angular不要销毁组件,但实际上可以保存它以供以后重新渲染。这很酷,因为它允许:

  • 减少服务器调用
  • 提高速度
  • 组件呈现,默认情况下,在相同的状态有人离开

如果您想暂时离开一个页面,即使用户已经在其中输入了大量文本,最后一个也很重要由于表单数量过多企业应用程序会喜欢此功能

这就是我想出的解决问题的方法。正如您所说,您需要使用RouteReuseStrategy@angular/router 在 3.4.1 及更高版本中提供的。

去做

首先确保你的项目有@angular/router 3.4.1 或更高版本。

接下来,创建一个文件,该文件将容纳实现RouteReuseStrategy. 我打电话给我的reuse-strategy.ts,把它放在/app文件夹里妥善保管。现在,这个类应该是这样的:

import { RouteReuseStrategy } from '@angular/router';

export class CustomReuseStrategy implements RouteReuseStrategy {
}

(不要担心您的 TypeScript 错误,我们将解决所有问题)

完成了基础,提供了类的app.module请注意,您还没有编写CustomReuseStrategy,但应该继续编写importreuse-strategy.tsimport { RouteReuseStrategy } from '@angular/router';

@NgModule({
    [...],
    providers: [
        {provide: RouteReuseStrategy, useClass: CustomReuseStrategy}
    ]
)}
export class AppModule {
}

最后一部分是编写控制路由是否被分离、存储、检索和重新附加的类。在我们讨论旧的copy/paste 之前,我将在这里对机制做一个简短的解释,据我所知。对于我描述的方法,请参考下面的代码,当然,代码中有大量文档

  1. 当你导航时,shouldReuseRoute火。这个对我来说有点奇怪,但是如果它返回true,那么它实际上会重用您当前所在的路线,并且不会触发任何其他方法。如果用户正在导航,我只会返回 false。
  2. 如果shouldReuseRoute返回false,则shouldDetach触发。shouldDetach确定是否要存储路线,并返回一个boolean指示。这是您应该决定存储/不存储路径的地方,我将通过检查存储的路径数组来实现route.routeConfig.path,如果path数组中不存在则返回 false
  3. 如果shouldDetach返回truestore则被触发,这是您存储任何您想要的有关路线的信息的机会。无论您做什么,您都需要存储 ,DetachedRouteHandle因为 Angular 稍后会使用它来识别您存储的组件。下面,我将 theDetachedRouteHandle和 the存储ActivatedRouteSnapshot到我的类的本地变量中。

所以,我们已经看到了存储的逻辑,但是导航一个组件呢?Angular 如何决定拦截你的导航并将存储的导航放在它的位置?

  1. 同样, after shouldReuseRoutehas返回falseshouldAttach运行,这是您确定是否要重新生成或在内存中使用组件的机会。如果您想重用已存储的组件,请返回true,一切顺利!
  2. 现在 Angular 会问你,“你想让我们使用哪个组件?”,你将通过返回该组件的DetachedRouteHandlefrom来指示retrieve

这几乎就是您需要的所有逻辑!reuse-strategy.ts下面的 代码中,我还为您留下了一个比较两个对象的漂亮函数。我用它来比较未来的路线route.paramsroute.queryParams存储的路线如果这些都匹配,我想使用存储的组件而不是生成一个新的组件。但是你怎么做取决于你!

重用策略.ts

/**
 * reuse-strategy.ts
 * by corbfon 1/6/17
 */

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 {

    /** 
     * Object which will store RouteStorageObjects indexed by keys
     * The keys will all be a path (as in route.routeConfig.path)
     * This allows us to see if we've got a route stored for the requested path
     */
    storedRoutes: { [key: string]: RouteStorageObject } = {};

    /** 
     * Decides when the route should be stored
     * If the route should be stored, I believe the boolean is indicating to a controller whether or not to fire this.store
     * _When_ it is called though does not particularly matter, just know that this determines whether or not we store the route
     * An idea of what to do here: check the route.routeConfig.path to see if it is a path you would like to store
     * @param route This is, at least as I understand it, the route that the user is currently on, and we would like to know if we want to store it
     * @returns boolean indicating that we want to (true) or do not want to (false) store that route
     */
    shouldDetach(route: ActivatedRouteSnapshot): boolean {
        let detach: boolean = true;
        console.log("detaching", route, "return: ", detach);
        return detach;
    }

    /**
     * Constructs object of type `RouteStorageObject` to store, and then stores it for later attachment
     * @param route This is stored for later comparison to requested routes, see `this.shouldAttach`
     * @param handle Later to be retrieved by this.retrieve, and offered up to whatever controller is using this class
     */
    store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
        let storedRoute: RouteStorageObject = {
            snapshot: route,
            handle: handle
        };

        console.log( "store:", storedRoute, "into: ", this.storedRoutes );
        // routes are stored by path - the key is the path name, and the handle is stored under it so that you can only ever have one object stored for a single path
        this.storedRoutes[route.routeConfig.path] = storedRoute;
    }

    /**
     * Determines whether or not there is a stored route and, if there is, whether or not it should be rendered in place of requested route
     * @param route The route the user requested
     * @returns boolean indicating whether or not to render the stored route
     */
    shouldAttach(route: ActivatedRouteSnapshot): boolean {

        // this will be true if the route has been stored before
        let canAttach: boolean = !!route.routeConfig && !!this.storedRoutes[route.routeConfig.path];

        // this decides whether the route already stored should be rendered in place of the requested route, and is the return value
        // at this point we already know that the paths match because the storedResults key is the route.routeConfig.path
        // so, if the route.params and route.queryParams also match, then we should reuse the component
        if (canAttach) {
            let willAttach: boolean = true;
            console.log("param comparison:");
            console.log(this.compareObjects(route.params, this.storedRoutes[route.routeConfig.path].snapshot.params));
            console.log("query param comparison");
            console.log(this.compareObjects(route.queryParams, this.storedRoutes[route.routeConfig.path].snapshot.queryParams));

            let paramsMatch: boolean = this.compareObjects(route.params, this.storedRoutes[route.routeConfig.path].snapshot.params);
            let queryParamsMatch: boolean = this.compareObjects(route.queryParams, this.storedRoutes[route.routeConfig.path].snapshot.queryParams);

            console.log("deciding to attach...", route, "does it match?", this.storedRoutes[route.routeConfig.path].snapshot, "return: ", paramsMatch && queryParamsMatch);
            return paramsMatch && queryParamsMatch;
        } else {
            return false;
        }
    }

    /** 
     * Finds the locally stored instance of the requested route, if it exists, and returns it
     * @param route New route the user has requested
     * @returns DetachedRouteHandle object which can be used to render the component
     */
    retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {

        // return null if the path does not have a routerConfig OR if there is no stored route for that routerConfig
        if (!route.routeConfig || !this.storedRoutes[route.routeConfig.path]) return null;
        console.log("retrieving", "return: ", this.storedRoutes[route.routeConfig.path]);

        /** returns handle when the route.routeConfig.path is already stored */
        return this.storedRoutes[route.routeConfig.path].handle;
    }

    /** 
     * Determines whether or not the current route should be reused
     * @param future The route the user is going to, as triggered by the router
     * @param curr The route the user is currently on
     * @returns boolean basically indicating true if the user intends to leave the current route
     */
    shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
        console.log("deciding to reuse", "future", future.routeConfig, "current", curr.routeConfig, "return: ", future.routeConfig === curr.routeConfig);
        return future.routeConfig === curr.routeConfig;
    }

    /** 
     * This nasty bugger finds out whether the objects are _traditionally_ equal to each other, like you might assume someone else would have put this function in vanilla JS already
     * One thing to note is that it uses coercive comparison (==) on properties which both objects have, not strict comparison (===)
     * Another important note is that the method only tells you if `compare` has all equal parameters to `base`, not the other way around
     * @param base The base object which you would like to compare another object to
     * @param compare The object to compare to base
     * @returns boolean indicating whether or not the objects have all the same properties and those properties are ==
     */
    private compareObjects(base: any, compare: any): boolean {

        // loop through all properties in base object
        for (let baseProperty in base) {

            // determine if comparrison object has that property, if not: return false
            if (compare.hasOwnProperty(baseProperty)) {
                switch(typeof base[baseProperty]) {
                    // if one is object and other is not: return false
                    // if they are both objects, recursively call this comparison function
                    case 'object':
                        if ( typeof compare[baseProperty] !== 'object' || !this.compareObjects(base[baseProperty], compare[baseProperty]) ) { return false; } break;
                    // if one is function and other is not: return false
                    // if both are functions, compare function.toString() results
                    case 'function':
                        if ( typeof compare[baseProperty] !== 'function' || base[baseProperty].toString() !== compare[baseProperty].toString() ) { return false; } break;
                    // otherwise, see if they are equal using coercive comparison
                    default:
                        if ( base[baseProperty] != compare[baseProperty] ) { return false; }
                }
            } else {
                return false;
            }
        }

        // returns true only after false HAS NOT BEEN returned through all loops
        return true;
    }
}

行为

此实现存储用户在路由器上访问的每条唯一路由仅一次。这将在用户在站点上的整个会话期间继续添加到存储在内存中的组件。如果您想限制您存储的路线,那么shouldDetach方法就是这样做的地方它控制您保存哪些路线。

例子

假设您的用户从主页搜索某些内容search/:term,这会将他们导航到路径,该路径可能显示为www.yourwebsite.com/search/thingsearchedfor搜索页面包含一堆搜索结果。你想存储这条路线,以防他们想回来!现在,他们点击一个搜索结果,并获得导航到view/:resultId,你希望店,看到他们很可能会出现一次。有了上面的实现,我会简单地改变shouldDetach方法!它可能如下所示:

首先让我们创建一个我们想要存储的路径数组。

private acceptedRoutes: string[] = ["search/:term"];

现在,shouldDetach我们可以检查route.routeConfig.path我们的数组。

shouldDetach(route: ActivatedRouteSnapshot): boolean {
    // check to see if the route's path is in our acceptedRoutes array
    if (this.acceptedRoutes.indexOf(route.routeConfig.path) > -1) {
        console.log("detaching", route);
        return true;
    } else {
        return false; // will be "view/:resultId" when user navigates to result
    }
}

因为 Angular只会存储一个路由实例,这个存储将是轻量级的,我们只会存储位于 的组件search/:term而不是所有其他的!

附加链接

尽管目前还没有太多文档,但这里有几个指向现有内容的链接:

Angular 文档:https : //angular.io/docs/ts/latest/api/router/index/RouteReuseStrategy-class.html

介绍文章:https : //www.softwarearchitekt.at/post/2016/12/02/sticky-routes-in-angular-2-3-with-routereusestrategy.aspx

nativescript棱角的默认实现RouteReuseStrategyhttps://github.com/NativeScript/nativescript-angular/blob/cb4fd3a/nativescript-angular/router/ns-route-reuse-strategy.ts

ReuseRouteStrategy 会将你的组件交还给路由器,所以它会处于它离开的任何状态。如果你想让组件对附件做出反应,你可以使用提供Observable. 组件应该订阅ObservableduringngOnInit生命周期钩子。然后,您将能够从 中告诉组件ReuseRouteStrategy它刚刚被附加并且该组件可以修改其状态以适合。
2021-03-23 01:15:09
有没有办法让它在重新激活存储的路线时重新运行输入动画?
2021-03-28 01:15:09
@AndersGramMygind 如果我的回答为您提出的问题提供了答案,您会将其标记为答案吗?
2021-03-28 01:15:09
@shaahin 我添加了一个示例,这是我当前实现中包含的确切代码!
2021-04-09 01:15:09
@Corbfon 我也在官方 github 页面上打开了一个问题:github.com/angular/angular/issues/13869
2021-04-11 01:15:09

不要被接受的答案吓倒,这很简单。这是您需要的快速答案。我建议至少阅读已接受的答案,因为它充满了细节。

该解决方案不会像接受的答案那样进行任何参数比较,但它可以很好地存储一组路由。

app.module.ts 导入:

import { RouteReuseStrategy } from '@angular/router';
import { CustomReuseStrategy, Routing } from './shared/routing';

@NgModule({
//...
providers: [
    { provide: RouteReuseStrategy, useClass: CustomReuseStrategy },
  ]})

共享/路由.ts:

export class CustomReuseStrategy implements RouteReuseStrategy {
 routesToCache: string[] = ["dashboard"];
 storedRouteHandles = new Map<string, DetachedRouteHandle>();

 // Decides if the route should be stored
 shouldDetach(route: ActivatedRouteSnapshot): boolean {
    return this.routesToCache.indexOf(route.routeConfig.path) > -1;
 }

 //Store the information for the route we're destructing
 store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
    this.storedRouteHandles.set(route.routeConfig.path, handle);
 }

//Return true if we have a stored route object for the next route
 shouldAttach(route: ActivatedRouteSnapshot): boolean {
    return this.storedRouteHandles.has(route.routeConfig.path);
 }

 //If we returned true in shouldAttach(), now return the actual route data for restoration
 retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
    return this.storedRouteHandles.get(route.routeConfig.path);
 }

 //Reuse the route if we're going to and from the same route
 shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
    return future.routeConfig === curr.routeConfig;
 }
}
这也适用于延迟加载的路由吗?
2021-03-17 01:15:09
routeConfig 为 null,对于不同的路由,因此 shouldReuseRoute 将始终返回 true,这不是所需的行为
2021-04-08 01:15:09

除了已接受的答案(由 Corbfon 提供)和 Chris Fremgen 更简短、更直接的解释之外,我想添加一种更灵活的方式来处理应该使用重用策略的路由。

两个答案都将我们想要缓存的路由存储在一个数组中,然后检查当前路由路径是否在数组中。这个检查是在shouldDetach方法中完成的

我发现这种方法不灵活,因为如果我们想更改路线的名称,我们需要记住还要更改我们CustomReuseStrategyclass中的路线名称我们可能忘记更改它,或者我们团队中的某些其他开发人员可能决定更改路由名称,甚至不知道RouteReuseStrategy.

我们可以直接在RouterModuleusing dataobject 中标记它们,而不是将我们想要缓存的路由存储在数组中这样即使我们更改了路由名称,仍然会应用重用策略。

{
  path: 'route-name-i-can-change',
  component: TestComponent,
  data: {
    reuseRoute: true
  }
}

然后在shouldDetach方法中我们使用它。

shouldDetach(route: ActivatedRouteSnapshot): boolean {
  return route.data.reuseRoute === true;
}
很好的解决方案。这真的应该用一个像您应用的简单标志来烘焙到标准的角度路线重用策略中。
2021-04-04 01:15:09
很好的答案。非常感谢你!
2021-04-07 01:15:09
最后,我找到了一个可以在 2 分钟内实现的答案,而无需深入研究 angular 的内容和原因。哈哈。
2021-04-07 01:15:09

另一个更有效、更完整和可重用的实现。这个支持延迟加载module作为@Uğur Dinç 并集成@Davor 路由数据标志。最好的改进是基于页面绝对路径自动生成(几乎)唯一标识符。这样您就不必在每一页上自己定义它。

标记要缓存设置的任何页面reuseRoute: true将在shouldDetach方法中使用。

{
  path: '',
  component: MyPageComponent,
  data: { reuseRoute: true },
}

这是最简单的策略实现,没有比较查询参数。

import { ActivatedRouteSnapshot, RouteReuseStrategy, DetachedRouteHandle, UrlSegment } from '@angular/router'

export class CustomReuseStrategy implements RouteReuseStrategy {

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

  shouldDetach(route: ActivatedRouteSnapshot): boolean {
    return route.data.reuseRoute || false;
  }

  store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
    const id = this.createIdentifier(route);
    if (route.data.reuseRoute) {
      this.storedHandles[id] = handle;
    }
  }

  shouldAttach(route: ActivatedRouteSnapshot): boolean {
    const id = this.createIdentifier(route);
    const handle = this.storedHandles[id];
    const canAttach = !!route.routeConfig && !!handle;
    return canAttach;
  }

  retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
    const id = this.createIdentifier(route);
    if (!route.routeConfig || !this.storedHandles[id]) return null;
    return this.storedHandles[id];
  }

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

  private createIdentifier(route: ActivatedRouteSnapshot) {
    // Build the complete path from the root to the input route
    const segments: UrlSegment[][] = route.pathFromRoot.map(r => r.url);
    const subpaths = ([] as UrlSegment[]).concat(...segments).map(segment => segment.path);
    // Result: ${route_depth}-${path}
    return segments.length + '-' + subpaths.join('/');
  }
}

这个也比较了查询参数。compareObjects比@Corbfon 版本有一点改进:循环访问基础和比较对象的属性。请记住,您可以使用外部且更可靠的实现,例如 lodashisEqual方法。

import { ActivatedRouteSnapshot, RouteReuseStrategy, DetachedRouteHandle, UrlSegment } from '@angular/router'

interface RouteStorageObject {
  snapshot: ActivatedRouteSnapshot;
  handle: DetachedRouteHandle;
}

export class CustomReuseStrategy implements RouteReuseStrategy {

  storedRoutes: { [key: string]: RouteStorageObject } = {};

  shouldDetach(route: ActivatedRouteSnapshot): boolean {
    return route.data.reuseRoute || false;
  }

  store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
    const id = this.createIdentifier(route);
    if (route.data.reuseRoute && id.length > 0) {
      this.storedRoutes[id] = { handle, snapshot: route };
    }
  }

  shouldAttach(route: ActivatedRouteSnapshot): boolean {
    const id = this.createIdentifier(route);
    const storedObject = this.storedRoutes[id];
    const canAttach = !!route.routeConfig && !!storedObject;
    if (!canAttach) return false;

    const paramsMatch = this.compareObjects(route.params, storedObject.snapshot.params);
    const queryParamsMatch = this.compareObjects(route.queryParams, storedObject.snapshot.queryParams);

    console.log('deciding to attach...', route, 'does it match?');
    console.log('param comparison:', paramsMatch);
    console.log('query param comparison', queryParamsMatch);
    console.log(storedObject.snapshot, 'return: ', paramsMatch && queryParamsMatch);

    return paramsMatch && queryParamsMatch;
  }

  retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
    const id = this.createIdentifier(route);
    if (!route.routeConfig || !this.storedRoutes[id]) return null;
    return this.storedRoutes[id].handle;
  }

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

  private createIdentifier(route: ActivatedRouteSnapshot) {
    // Build the complete path from the root to the input route
    const segments: UrlSegment[][] = route.pathFromRoot.map(r => r.url);
    const subpaths = ([] as UrlSegment[]).concat(...segments).map(segment => segment.path);
    // Result: ${route_depth}-${path}
    return segments.length + '-' + subpaths.join('/');
  }

  private compareObjects(base: any, compare: any): boolean {

    // loop through all properties
    for (const baseProperty in { ...base, ...compare }) {

      // determine if comparrison object has that property, if not: return false
      if (compare.hasOwnProperty(baseProperty)) {
        switch (typeof base[baseProperty]) {
          // if one is object and other is not: return false
          // if they are both objects, recursively call this comparison function
          case 'object':
            if (typeof compare[baseProperty] !== 'object' || !this.compareObjects(base[baseProperty], compare[baseProperty])) {
              return false;
            }
            break;
          // if one is function and other is not: return false
          // if both are functions, compare function.toString() results
          case 'function':
            if (typeof compare[baseProperty] !== 'function' || base[baseProperty].toString() !== compare[baseProperty].toString()) {
              return false;
            }
            break;
          // otherwise, see if they are equal using coercive comparison
          default:
            // tslint:disable-next-line triple-equals
            if (base[baseProperty] != compare[baseProperty]) {
              return false;
            }
        }
      } else {
        return false;
      }
    }

    // returns true only after false HAS NOT BEEN returned through all loops
    return true;
  }
}

如果您有生成唯一键的最佳方法,请评论我的答案,我将更新代码。

感谢所有分享他们解决方案的人。

很棒的解决方案!只是提一下,如果您想在用户注销时删除存储的组件,您可以在shouldAttach钩子中执行类似的操作if (route.component === AuthComponent ){ this.storedHandles = {}; return false; }
2021-03-13 01:15:09
如果我{ path: '', component: UsersComponent, children: [ { path: ':id', component: UserComponent, data: { reuseRoute: true } } ] }在这种情况下有像UserComponent这样的配置缓存在/user/1 -> /users -> /user/2预期的场景中,但是它什么时候会被销毁?即使我尝试远离父UsersComponent /users -> /something-else,该路由仍然处于活动状态。所以我只想了解它什么时候会被摧毁?
2021-03-15 01:15:09
这应该是公认的答案。上面提供的许多解决方案不能支持具有相同子 URL 的多个页面。因为他们比较的是activatedRoute URL,不是完整路径。
2021-03-17 01:15:09

要对延迟加载的module使用 Chris Fremgen 的策略,请将 CustomReuseStrategy 类修改为以下内容:

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

export class CustomReuseStrategy implements RouteReuseStrategy {
  routesToCache: string[] = ["company"];
  storedRouteHandles = new Map<string, DetachedRouteHandle>();

  // Decides if the route should be stored
  shouldDetach(route: ActivatedRouteSnapshot): boolean {
     return this.routesToCache.indexOf(route.data["key"]) > -1;
  }

  //Store the information for the route we're destructing
  store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
     this.storedRouteHandles.set(route.data["key"], handle);
  }

  //Return true if we have a stored route object for the next route
  shouldAttach(route: ActivatedRouteSnapshot): boolean {
     return this.storedRouteHandles.has(route.data["key"]);
  }

  //If we returned true in shouldAttach(), now return the actual route data for restoration
  retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
     return this.storedRouteHandles.get(route.data["key"]);
  }

  //Reuse the route if we're going to and from the same route
  shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
     return future.routeConfig === curr.routeConfig;
  }
}

最后,在您的功能module的路由文件中,定义您的密钥:

{ path: '', component: CompanyComponent, children: [
    {path: '', component: CompanyListComponent, data: {key: "company"}},
    {path: ':companyID', component: CompanyDetailComponent},
]}

更多信息在这里

感谢您添加此内容!我得试一试。它甚至可以解决我的解决方案遇到的一些子路由处理问题。
2021-03-15 01:15:09
我不得不使用route.data["key"]构建而不会出错。但我遇到的问题是我有一个在两个不同地方使用的路由+组件。1. sample/list/item2. product/id/sample/list/item当我第一次加载任何的路径,它加载罚款,但其他投重新连接错误,因为我是基于存储list/item所以我的解决办法是我复制的路线,并提出了一些变化的URL路径,但显示相同的组件。不确定是否有其他解决方法。
2021-03-20 01:15:09
这让我很困惑,上面的方法是行不通的,只要我点击我的缓存路由之一,它就会爆炸(它不再导航,并且控制台中出现错误)。据我所知,Chris Fremgen 的解决方案似乎适用于我的懒惰module......
2021-03-28 01:15:09