现在我正在研究守卫。我在文档中读到了这个陈述。
The router checks the CanDeactivate and CanActivateChild guards first,from the deepest child route to the top. Then it checks the CanActivate guards from the top down to the deepest child route.
现在我很困惑,为什么角度以这种方式表现呢?
CanDeactivate& amp;是否有从最深的孩子到顶部进行检查的任何好处? CanActivateChild。从顶部到CanActivate最深的儿童路线?
简要说明:
首先,从最深到最顶层检查CanDeactivate防护,并从顶部到最深处检查CanActivate防护(它将在遍历中退出并进行错误检查)。
其次,CanActivateChild守卫不会从最深层到最高层进行检查。
TL; DR
详细说明
我们应该查看源代码,看看它是如何工作的。
Note: the commit checked is: 07000
第1步 – 查看CanActivateChild何时被调用
这只是其高级调用者runCanActivateChild被调用的地方。
在那一行,我们可以得到一些暗示它与CanActivate做同样的技巧,因为CanActivate的优秀调用者runCanActivate被调用。
第2步 – 看看runCanActivateChild是如何工作的
runCanActivateChild在canActivateChecks的迭代中被调用,与调用runCanActivate的方式相同。在这里,我们知道CanActivate(我的意思是该功能)和CanActivateChild共享相同的数据源 – canActivateChecks。
第3步 – 什么是canActivateChecks以及如何处理它
那么,什么是canActivateChecks?显然,我们可以发现它是CanActivate类实例的数组。但是如何分配canActivateChecks? Go to here L865.这是重要的部分,所以我打算将它们粘贴在这里。
private traverseChildRoutes( futureNode: TreeNode<ActivatedRouteSnapshot>,currNode: TreeNode<ActivatedRouteSnapshot>|null,contexts: ChildrenOutletContexts|null,futurePath: ActivatedRouteSnapshot[]): void { const prevChildren = nodeChildrenAsMap(currNode); // Process the children of the future route futureNode.children.forEach(c => { this.traverseRoutes(c,prevChildren[c.value.outlet],contexts,futurePath.concat([c.value])); delete prevChildren[c.value.outlet]; }); // Process any children left from the current route (not active for the future route) forEach( prevChildren,(v: TreeNode<ActivatedRouteSnapshot>,k: string) => this.deactivateRouteAndItsChildren(v,contexts !.getContext(k))); } private traverseRoutes( futureNode: TreeNode<ActivatedRouteSnapshot>,currNode: TreeNode<ActivatedRouteSnapshot>,parentContexts: ChildrenOutletContexts|null,futurePath: ActivatedRouteSnapshot[]): void { const future = futureNode.value; const curr = currNode ? currNode.value : null; const context = parentContexts ? parentContexts.getContext(futureNode.value.outlet) : null; // reusing the node if (curr && future._routeConfig === curr._routeConfig) { if (this.shouldRunGuardsAndResolvers( curr,future,future._routeConfig !.runGuardsAndResolvers)) { this.canActivateChecks.push(new CanActivate(futurePath)); const outlet = context !.outlet !; this.canDeactivateChecks.push(new CanDeactivate(outlet.component,curr)); } else { // we need to set the data future.data = curr.data; future._resolvedData = curr._resolvedData; } // If we have a component,we need to go through an outlet. if (future.component) { this.traverseChildRoutes( futureNode,currNode,context ? context.children : null,futurePath); // if we have a componentless route,we recurse but keep the same outlet map. } else { this.traverseChildRoutes(futureNode,parentContexts,futurePath); } } else { // ##### comment by e-cloud ##### if (curr) { this.deactivateRouteAndItsChildren(currNode,context); } this.canActivateChecks.push(new CanActivate(futurePath)); // If we have a component,we need to go through an outlet. if (future.component) { this.traverseChildRoutes(futureNode,null,futurePath); } } }
这有点长。但是如果你经历它,你会发现它会进行深度优先遍历。让我们忽略相同的路由切换。通过e-cloud #####查找#####评论并查看主要程序。它显示它首先更新canActivateChecks然后执行下一级别的travesal(整个预订遍历)。
您必须知道路由器将应用程序的所有路由视为URL树。每个PreActivation通过遍历将其未来(作为树路径)分成路径段。
举个简单的例子:
we have the future route as
/a/b/c
.
Then we will get [ ‘/a’,‘/a/b’,‘/a/b/c’ ] ascanActivateChecks
显然,canActivateChecks代表了从最高层到最深层的路线
源显示canActivateChecks从左到右迭代。
第4步 – 结论
我们可以得出结论,CanActivateChild是从最顶层到最深的孩子。
希望我能清楚地解释清楚。