我正在努力深入了解角度,所以我读了the docs,这非常有帮助
现在我正在研究守卫。我在文档中读到了这个陈述。
路由器首先检查CanDeactivate和CanActivateChild防护,从最深的子路由到顶部。然后它从上到下检查CanActivate警卫到最深的子路线。
现在我很困惑,为什么角度以这种方式表现呢? 对于 CanDeactivate &amp ;;从最深的孩子到顶部进行检查是否有任何好处?的 CanActivateChild 即可。从 CanActivate 到最深的儿童路线?
答案 0 :(得分:14)
我曾试图相信文档网站上的内容。但是,它似乎并不完全正确,或者实施已更新但文档无法更新。
简要说明:
首先,从最深层检查CanDeactivate
防护,并从从最顶层检查{/ 1}}防护(它将退出,在遍历中使用falsy check。)
其次,不会从最深层检查CanActivate
警卫。
TL; DR
我们应该查看来源以了解它是如何工作的。
注意:检查的提交是:https://github.com/angular/angular/tree/edb8375a5ff15d77709ccf1759efb14091fa86a4
CanActivateChild
这只是调用其优秀来电者CanActivateChild
的地方。
在那一行,我们可以得到一些暗示它与runCanActivateChild
做同样的技巧,因为CanActivate
的高级调用者CanActivate
被调用。
runCanActivate
如何运作runCanActivateChild
的迭代中调用了{p> runCanActivateChild
,与调用canActivateChecks
的方式相同。我们知道runCanActivate
(我的意思是该功能)和CanActivate
共享相同的数据源 - CanActivateChild
。
canActivateChecks
以及如何处理那么,canActivateChecks
是什么?显然,我们可以发现它是canActivateChecks
类实例的数组。但是如何分配CanActivate
? Go to here L865。这是重要的部分,所以我将它们粘贴在这里。
canActivateChecks
有点长。但是如果你经历它,你会发现它会播放深度优先遍历。让我们忽略相同的路由切换。查找 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, currNode, 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, context ? context.children : null, futurePath);
// if we have a componentless route, we recurse but keep the same outlet map.
} else {
this.traverseChildRoutes(futureNode, null, parentContexts, futurePath);
}
}
}
并查看主要步骤。它显示它首先更新##### comment by e-cloud #####
然后执行下一级别的travesal(整个预订遍历)。
您必须知道路由器会将应用的所有路由视为网址树。每个canActivateChecks
通过遍历将其PreActivation
(作为树路径)拆分为路径段。
采用简化示例:
我们的未来路线为
future
然后我们会得到[&#39; / a&#39;,&#39; / a / b&#39;,&#39; / a / b / c&#39; ]/a/b/c
显然,canActivateChecks
代表canActivateChecks
从最顶层到最深层的路线
源代码显示future
从左到右迭代。
我们可以得出结论,canActivateChecks
是从最顶层到最深的孩子。
希望我能清楚地解释清楚。
答案 1 :(得分:4)
当你考虑路由时,你去的树越深,你获得的具体越多。
例如:
/food-types/sweets/pies/blueberry
因此,当您告诉Angular您希望离开blueberry
饼时,它首先会检查蓝莓上的CanDeactivate
,因为您正在向上返回导航树,到另一个位置。根据我的理解,CanActivateChild
也会走到树的路径上,出于同样的原因:它想先检查最深层次,以验证他们的孩子是否可以被激活。
与CanActivate
相反。当你告诉Angular你想要看到blueberry
馅饼时,你正沿着树走下去,因此,当它沿着树走下去的时候,它会检查卫兵。