关于路由复用策略网上的文章不少,大可能是讲如何实现tab标签切换历史数据,至于如何复用的原理讲的都比较朦胧,代码样例也很难适用各类各样的路由配置,好比懒加载模式下多级嵌套路由出口网上的大部分代码都会报错。
我但愿能经过这篇文章把如何复用路由的原理讲明白,让小伙伴能明明白白的实用路由复用策略,文字中有不详实和错误的地方欢迎小伙伴批评指正
路由复用策略的是对路由的父级相同节点的组件实例的复用,咱们平时看到的多级嵌套路由切换时上层路由出口的实例并不会重新实例化就是由于angular默认的路由复用策略在起做用,而咱们从写路由复用策略能实现不少事情,其中之一就是实现
历史路由状态(数据)的存储,即jquery时代的tab页签和iframe实现操做历史的切换。jquery
我一开始认为路由复用策略就是对历史路由数据的复用策略,这个错误的观念致使我对路由复用策略接口方法理解起来异常困难,不知小伙伴和我犯没犯一样的错误。观念正确了,下面就理解起来比较方便了,写路由复用策略也就比较顺手了。缓存
下面是angular默认路由复用策略,每切换一下路由,下面代码都再默默的执行。code
export class DefaultRouteReuseStrategy { shouldDetach(route) { return false; } store(route, detachedTree) { } shouldAttach(route) { return false; } retrieve(route) { return null; } shouldReuseRoute(future, curr) { return future.routeConfig === curr.routeConfig; } }
开始文章前咱们先了解几个观念概念
RouterModule.forRoot(Routes)
,RouterModule.forChild(Routes)
这些配置最后造成一个完整的路由树,路由树有个根是没有routeConfig
的,routeConfig
是咱们写的每一个route
。route
配置了component,有的则没有shouldReuseRoute(future, curr)
retrieve(route)
shouldDetach(route)
store(route, detachedTree)
shouldAttach(route)
retrieve
,取决一上一步的返回值store(route, detachedTree)
,取决第五步shouldReuseRoute
shouldReuseRoute()
决定是否复用路由,根据切换的future
curr
的节点层级依次调用,返回值为true时表示当前节点层级路由复用,而后继续下一路由节点调用,入参为切换的下一级路由(子级)的future
curr
路由的节点,返回值为false时表示不在复用路由,而且再也不继续调用此方法(future
路由再也不复用,其子级路由也不会复用,因此不须要再询问下去),root路由节点调用一次,非root路由节点调用两次这个方法,第一次比较父级节点,第二次比较当前节点,component
retrieve
retrieve()
接上一步奏,当当前层级路由不须要复用的时候,调用一下retrieve
方法,其子级路由也会调用一下retrieve
方法,若是返回的是null,那么当前路由对应的组件会实例化,这种行为一直持续到末级路由。router
shouldDetach
shouldDetach
是对上一路由的数据是否实现拆离,其调用开始是当前层级路由不须要复用的时候,即shouldReuseRoute()
返回false的时候,若是这时候反回false,将继续到上一路由的下一层级调用shouldDetach
,直到返回true或者是最末级路由后才结束对shouldDetach
的调用,当返回true时就调用一次store
方法,请看下一步奏接口
store
store
存储路分离出来的上一路由的数据,当 shouldDetach
返回true时调用一次,存储应该被分离的那一层的路由的DetachedRouteHandle
。注意:不管路由树上多个含有组件component
路由节点,能分离出来的只能有一个,被存储的也只能有一个,感受这种机制对使用场景有很大限制。路由
shouldAttach
shouldAttach
是对当前路由的数据是否实现恢复(附加回来),其调用开始是当前层级路由不须要复用的时候,即shouldReuseRoute()
返回false的时候,这和shouldDetach
的调用时机很像,可是,并非全部的路由层级都是有组件实例的,只有包含component
的route
才会触发shouldAttach
,若是反回false,将继续到当前路由的下一带有component
的路由层级调用shouldAttach
,直到返回true或者是最末级路由后才结束对shouldAttach
的调用,当返回true时就调用一次retrieve
方法,若是retrieve
方法去获取一下当前路由的DetachedRouteHandle
,返回一个DetachedRouteHandle
,就再调用一次store
,再保存一下retrieve
返回的DetachedRouteHandle
。注意注意:不管路由树上多个含有组件component
路由节点,能恢复数据的只能有一个节点,这和shouldDetach
是一个套路,对使用场景有很大限制。get
路由复用策略这种调用机制对使用场景限制很大 ,好比多级路由出口嵌套就没法实现路由数据缓存。由于多级路由出口嵌套的应用切换路由时,先后路由会包含多个带component的路由节点,而每次对路由的存储和恢复只能存储和恢复某一个节点的component的DetachedRouteHandle
,其余路由节点上的component就是被重新实例化。明白这一点后我就放弃了想写一个能够适用任何场景的路由复用策略的想法,若是有小伙伴能解决好这一业务场景,欢迎赐教。 iframe
若是这个路由复用策略能够存储一个路由上多个节点的DetachedRouteHandle
,和恢复多个节点的DetachedRouteHandle
,应该能解决上面是的多级路由出口嵌套场景,但不知道会不会带来别的问题。class
下面贴一个路由复用策略用例,应该是知足大部分人的业务要求,注意事项:只能是末级路由的缓存,且路由切换的时候路由节点上的component不能超过两个。
import {ActivatedRouteSnapshot, DetachedRouteHandle, Route, RouteReuseStrategy} from "@angular/router"; export class CustomerReuseStrategy implements RouteReuseStrategy { static handlers: Map<Route, DetachedRouteHandle> = new Map(); shouldDetach(route: ActivatedRouteSnapshot): boolean { return !route.firstChild; } shouldAttach(route: ActivatedRouteSnapshot): boolean { return !!CustomerReuseStrategy.handlers.has(route.routeConfig); } shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot) { return curr.routeConfig === future.routeConfig; } retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle { if (!!route.firstChild) { return null; } return CustomerReuseStrategy.handlers.get(route.routeConfig); } store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void { CustomerReuseStrategy.handlers.set(route.routeConfig, handle); } }
很精简,可是很好用,小伙伴能够根据本身的业务逻辑进行改造。
若是感受这篇文章对你有帮助,请点个赞吧 👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍