Angular 角度2实施路由使用策略

Angular 角度2实施路由使用策略,angular,routes,Angular,Routes,我实现了RouteReuseStrategy建议并进行了一些更新,因为在shoulldattach上,routeConfig.path为空,并且未缓存处理程序。我有@angular/router:3.4.7 import {RouteReuseStrategy, DetachedRouteHandle, ActivatedRouteSnapshot} from "@angular/router" export class CustomReuseStrategy implements Route

我实现了
RouteReuseStrategy
建议并进行了一些更新,因为在
shoulldattach
上,
routeConfig.path
为空,并且未缓存处理程序。我有
@angular/router:3.4.7

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

export class CustomReuseStrategy implements RouteReuseStrategy {

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

    shouldDetach(route: ActivatedRouteSnapshot): boolean {
        return true
    }

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

    shouldAttach(route: ActivatedRouteSnapshot): boolean {
        // todo route.routeConfig.path was empty
        if (!!this.currentPath && !!this.handlers[this.currentPath]) {
            route.routeConfig.path = this.currentPath;
            return true
        } else {
            return false
        }
    }

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

    shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
        this.currentPath = curr.routeConfig && curr.routeConfig.path;

        return future.routeConfig === curr.routeConfig
    }

    deleteHandler(handler:string) {
        this.handlers[handler] && delete this.handlers[handler]
    }

}
一切正常,但当我第三次尝试导航回某条路线时,出现以下错误:

EXCEPTION: Uncaught (in promise): Error: Cannot reattach ActivatedRouteSnapshot with a different number of children
Error: Cannot reattach ActivatedRouteSnapshot with a different number of children
    at setFutureSnapshotsOfActivatedRoutes (http://localhost:4200/js/vendor.bundle.js:93110:15) [angular]
    at createNode (http://localhost:4200/js/vendor.bundle.js:93091:9) [angular]
    at http://localhost:4200/js/vendor.bundle.js:93131:16 [angular]
    at Array.map (native) [angular]
    at createOrReuseChildren (http://localhost:4200/js/vendor.bundle.js:93124:26) [angular]
    at createNode (http://localhost:4200/js/vendor.bundle.js:93086:41) [angular]
    at http://localhost:4200/js/vendor.bundle.js:93128:24 [angular]
    at Array.map (native) [angular]
    at createOrReuseChildren (http://localhost:4200/js/vendor.bundle.js:93124:26) [angular]
    at createNode (http://localhost:4200/js/vendor.bundle.js:93086:41) [angular]
    at createRouterState (http://localhost:4200/js/vendor.bundle.js:93072:33) [angular]
    at MapSubscriber.project (http://localhost:4200/js/vendor.bundle.js:26366:153) [angular]
    at MapSubscriber._next (http://localhost:4200/js/vendor.bundle.js:15890:35) [angular]
    at MapSubscriber.Subscriber.next (http://localhost:4200/js/vendor.bundle.js:4861:18) [angular]
    at MergeMapSubscriber.notifyNext (http://localhost:4200/js/vendor.bundle.js:19133:30) [angular]
    at InnerSubscriber._next (http://localhost:4200/js/vendor.bundle.js:106234:21) [angular]
    at InnerSubscriber.Subscriber.next (http://localhost:4200/js/vendor.bundle.js:4861:18) [angular]
    at MapSubscriber._next (http://localhost:4200/js/vendor.bundle.js:15896:26) [angular]
    at MapSubscriber.Subscriber.next (http://localhost:4200/js/vendor.bundle.js:4861:18) [angular]
    at ReduceSubscriber._complete (http://localhost:4200/js/vendor.bundle.js:36808:30) [angular]
    at ReduceSubscriber.Subscriber.complete (http://localhost:4200/js/vendor.bundle.js:4886:18) [angular]
    at MergeMapSubscriber._complete (http://localhost:4200/js/vendor.bundle.js:19125:30) [angular]
    at MergeMapSubscriber.Subscriber.complete (http://localhost:4200/js/vendor.bundle.js:4886:18) [angular]
    at ArrayObservable._subscribe (http://localhost:4200/js/vendor.bundle.js:12465:24) [angular]
    at ArrayObservable.Observable._trySubscribe (http://localhost:4200/js/vendor.bundle.js:221:25) [angular]
    at ArrayObservable.Observable.subscribe (http://localhost:4200/js/vendor.bundle.js:209:27) [angular]
    at MergeMapOperator.call (http://localhost:4200/js/vendor.bundle.js:19075:23) [angular]
    at Observable.subscribe (http://localhost:4200/js/vendor.bundle.js:206:22) [angular]
    at ReduceOperator.call (http://localhost:4200/js/vendor.bundle.js:36763:23) [angular]
    at Observable.subscribe (http://localhost:4200/js/vendor.bundle.js:206:22) [angular]
    at MapOperator.call (http://localhost:4200/js/vendor.bundle.js:15867:23) [angular]
    at Observable.subscribe (http://localhost:4200/js/vendor.bundle.js:206:22) [angular]
    at Object.subscribeToResult (http://localhost:4200/js/vendor.bundle.js:5096:27) [angular]
...

我也有同样的问题,上个星期我一直在努力。我现在觉得很好用主要挑战是为任何给定路由定义唯一密钥。我发现RouterUseStrategy在为应用程序配置子路由和延迟加载时,理解和定义每个路由的密钥变得有点复杂。我试图解释我的理解,我希望这些信息能有所帮助

路由使用策略
我试图找出RouteReuseStrategy方法调用和参数详细信息,以生成唯一密钥,并通过调试我的应用程序得出以下图表。注意到有时会将阶段参数传递给方法调用,并尝试在RouterUseStrategy实现中忽略这些参数

客户重用策略

路由使用策略实施:

/* tslint:disable */
import {ActivatedRouteSnapshot, DetachedRouteHandle, Params, RouteReuseStrategy} from "@angular/router";

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

export class CustomReuseStrategy implements RouteReuseStrategy {
    storedRoutes: { [key: string]: RouteStorageObject } = {};

    getFurthestDecendantParams(route: ActivatedRouteSnapshot, sum: any): ActivatedRouteSnapshot {
        if (route.children.length > 0) {
            let child: ActivatedRouteSnapshot = route.children[0];
            sum.sum                           = sum.sum + this.sumParams(child.params);
            return this.getFurthestDecendantParams(child, sum);
        }
        return route;
    }

    sumParams(params: Params): string {
        return Object.keys(params).reduce((param, key) => {
            return param + params[key];
        }, "");
    }

    calcKey(route: ActivatedRouteSnapshot) {
        let paramKey = {
            sum: ""
        }
        if (route.children.length > 0) {
            this.getFurthestDecendantParams(route, paramKey).params;
        } else {
            paramKey.sum = this.sumParams(route.params);
        }
        if (paramKey.sum != "") {
            paramKey.sum = "_" + paramKey.sum;
        }
        return route.data.key + paramKey.sum;
    }

    public shouldDetach(route: ActivatedRouteSnapshot): boolean {
        console.info("CustomReuseStrategy.shouldDetach() - route key: " + this.calcKey(route));
        return !("product" === this.calcKey(route));
    }


    public store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
        let storedRoute: RouteStorageObject = {
            snapshot: route,
            handle: handle
        };
        console.info("CustomReuseStrategy.store() - route key: " + this.calcKey(route));
        this.storedRoutes[this.calcKey(route)] = storedRoute;
    }


    public shouldAttach(route: ActivatedRouteSnapshot): boolean {
        console.info("CustomReuseStrategy.shouldAttach() - route key: " + this.calcKey(route));
        return this.storedRoutes[this.calcKey(route)] !== undefined;
    }

    public retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
        console.info("CustomReuseStrategy.retrieve() - route key: " + this.calcKey(route));
        if (this.storedRoutes[this.calcKey(route)] === undefined) {
            /* Just return undefined */
            return null;
        } else {
            return this.storedRoutes[this.calcKey(route)].handle;
        }
    }


    public shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
        let returnValue = (future.routeConfig === curr.routeConfig);
        if (future.routeConfig != null && curr.routeConfig != null) {
            returnValue = this.calcKey(future) === this.calcKey(curr);
            console.info("CustomReuseStrategy.shouldReuseRoute() - future: " + this.calcKey(future) + ", curr: " + this.calcKey(curr) +
                ", future.routeConfig.path:" + future.routeConfig.path + ", curr.routeConfig.path:" + curr.routeConfig.path + ", returnValue: " + returnValue);
        } else {
            console.info("CustomReuseStrategy.shouldReuseRoute() - future: " + this.calcKey(future) + ", curr: " + this.calcKey(curr) +
                ", future.routeConfig:" + future.routeConfig + ", curr.routeConfig:" + curr.routeConfig + ", returnValue: " + returnValue);
        }
        return returnValue;
    }
}
总之

在我的应用程序和RouterUseStrategy中定义的以下内容很好

  • 使用数据键和子级延迟加载定义的路由
  • 只有单程出口
  • 每个路由的唯一密钥
  • 角度版本2.4.10和路由器版本3.4.10
参考


您的RouteReuseStrategy实施现在有效吗?不,它来自Angular:实际上,这个实施现在对我来说很有效,但我目前没有子路由:您找到解决方案了吗?我有一个类似的问题。nayakam,这里的“产品”是什么?@user1892775,这是为route配置的数据密钥。nayakam,我使用了您的方法来实现,我遇到了一些问题。也许你能帮忙,因为你对它很熟悉。我会非常感激的。这是我的帖子:@nayakam你能看看我的问题与此相关吗?