Angular 2实现RouteReuseStrategy [英] Angular 2 implementing RouteReuseStrategy

查看:77
本文介绍了Angular 2实现RouteReuseStrategy的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我实施了 RouteReuseStrategy 建议



CustomReuseStrategy



RouteReuseStrategy实施:

  / * tslint:disable * / 
从 @ angular / router导入{ActivatedRouteSnapshot,DetachedRouteHandle,Params,RouteReuseStrategy};

接口RouteStorageObject {
快照:ActivatedRouteSnapshot;
句柄:DetachedRouteHandle;
}

出口类CustomReuseStrategy实现RouteReuseStrategy {
storedRoutes:{[key:string]:RouteStorageObject} = {};

getFurthestDecendantParams(route:ActivatedRouteSnapshot,sum:any):ActivatedRouteSnapshot {
if(route.children.length> 0){
让孩子:ActivatedRouteSnapshot = route.children [ 0];
sum.sum = sum.sum + this.sumParams(child.params);
返回this.getFurthestDecendantParams(child,sum);
}
返回路线;
}

sumParams(params:Params):字符串{
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;
}
返回route.data.key + paramKey.sum;
}

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


公共商店(路由:ActivatedRouteSnapshot,句柄:DetachedRouteHandle):void {
let storageRoute:RouteStorageObject = {
快照:route,
handle:处理
};
console.info( CustomReuseStrategy.store()-路由键: + this.calcKey(route));
this.storedRoutes [this.calcKey(route)] = storedRoute;
}


public shouldAttach(route:ActivatedRouteSnapshot):boolean {
console.info( CustomReuseStrategy.shouldAttach()-路由键: + this.calcKey (路线));
返回this.storedRoutes [this.calcKey(route)]!==未定义;
}

公共检索(路线:ActivatedRouteSnapshot):DetachedRouteHandle {
console.info( CustomReuseStrategy.retrieve()-路线键: + this.calcKey(route)) ;
if(this.storedRoutes [this.calcKey(route)] ===未定义){
/ *只返回未定义* /
返回null;
}否则{
返回this.storedRoutes [this.calcKey(route)]。handle;
}
}


public ShouldReuseRoute(future:ActivatedRouteSnapshot,curr:ActivatedRouteSnapshot):布尔值{
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);
}否则{
console.info( CustomReuseStrategy.shouldReuseRoute()-future: + this.calcKey(future)+,curr: + this.calcKey(curr)+
,future.routeConfig: + future.routeConfig +,curr.routeConfig: + curr.routeConfig +,returnValue: + returnValue);
}
return returnValue;
}
}

摘要

以下内容在我的应用中定义,RouteReuseStrategy可以正常工作。




  • 使用数据定义路线密钥和子项的延迟加载

  • 仅单个路由出口

  • 每条路由的唯一密钥

  • 角度版本2.4.10和路由器版本3.4.10



参考




I implemented RouteReuseStrategy suggested here and also updated a bit, because on shouldAttach the routeConfig.path was empty, and the handler was not cached. I have @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]
    }

}

Everything is working, except when I try to navigate back the 3rd time to a route I got the following error:

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]
...

解决方案

I have same problem and was trying for last one week. Seems like it works fine for me now. Main challenge is defining a unique key for any given routes. I find RouteReuseStrategy become bit complex to understand and define key for each route when your configure you app with child routing and lazy loading. I try to explain my understanding and I hope this information helpful.

RouteReuseStrategy
I was trying to figure out the RouteReuseStrategy method calls and parameter details to generate unique key and come up with following diagram by debugging my application. Noticed sometimes stage parameters passed to method calls and try to ignore those parameters in RouteReuseStrategy implementation.

CustomReuseStrategy

RouteReuseStrategy Implementation:

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

In Summary

Following things define in my app and RouteReuseStrategy works fine.

  • Defined routes with data key and children lazy loading
  • Only single route-outlet
  • Unique key for each routes
  • Angular Version 2.4.10 and Router Version 3.4.10

Reference

这篇关于Angular 2实现RouteReuseStrategy的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆