警卫队,文档中的声明不明确 [英] Angular guards, unclear statement in the docs
问题描述
我试图深入了解角度,因此我阅读了文档,它非常有帮助.
现在我正在研究警卫.我在文档中阅读了此声明.
I'm trying to understand angular deeply, so i read the docs and it was very helpful.
now i'm studying the guards. and i read this statement in the docs.
从最深的子路由到顶部,路由器首先检查CanDeactivate和CanActivateChild防护.然后,它会从上到下检查最深的子路线的CanActivate防护.
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.
现在我很困惑,为什么angular会以这种方式执行它?
从最深的孩子到最上层的孩子检查 CanDeactivate &有什么好处? CanActivateChild .并从顶部到最深的子路径进行 CanActivate ?
now i'm confused, why does angular perform it in this way?
is there any benefits of doing the checking from the deepest child to the top for CanDeactivate & CanActivateChild. and from top to the deepest child route for CanActivate?
推荐答案
我试图相信docs网站中的内容.但是,这似乎并不完全正确,或者实现已更新,但是文档没有更新.
I had tried to believe what have written in the docs site. However, it appears it's not totally right, or the implementation has been updated but docs doesn't update.
要简短:
首先,从最深至最深检查CanDeactivate
防护,并从最深至最深检查CanActivate
防护(将退出 >虚假检查遍历.
First, CanDeactivate
guards are checked from deepest to top and CanActivate
guards are checked from top to deepest(it will quit with falsy check in the traversal).
第二,CanActivateChild
防护未从最深到最顶进行检查.
Second, CanActivateChild
guards are not checked from deepest to top.
TL; DR
我们应该检查源代码以了解其工作原理.
we should check the source to see how it work.
注意:检查的提交是: https://github.com/angular/angular/tree/edb8375a5ff15d77709ccf1759efb14091fa86a4
步骤1-查看何时调用CanActivateChild
step 1 - see when CanActivateChild
got called
source here L929.
这仅是其上级呼叫方runCanActivateChild
被呼叫的地方.
This is only place its superior caller runCanActivateChild
got called.
在那一行,我们可以得到一些提示,表明它的作用与CanActivate
相同,因为CanActivate
的上级调用方runCanActivate
是在之后被调用的.
At that line, we can get some hint that it does the same trick as CanActivate
, because CanActivate
's superior caller runCanActivate
is called after.
runCanActivateChild
在canActivateChecks
的迭代中被调用,与runCanActivate
的调用方式相同.在这里,我们知道CanActivate
(我是指功能)和CanActivateChild
共享相同的数据源-canActivateChecks
.
runCanActivateChild
got called within the iteration of canActivateChecks
, same as how runCanActivate
got called. Here we know CanActivate
(i mean the feature) and CanActivateChild
share the same data source -- canActivateChecks
.
那么,canActivateChecks
是什么?显然,我们可以发现它是CanActivate
类实例的数组.但是如何分配canActivateChecks
? 转到此处L865 .这是重要的部分,所以我要在这里粘贴它们.
So, what is canActivateChecks
? Obviously, We can find out it's an array of CanActivate
class instances. But how is canActivateChecks
got assigned? Go to here L865. This is the important part, so i am going to paste them here.
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);
}
}
}
有点长.但是,如果您经过它,就会发现它播放了 depth-first-traversal .让我们忽略相同的路由切换.找到##### comment by e-cloud #####
并查看主要过程.它显示出它首先更新canActivateChecks
然后执行下一级遍历(整体上是遍历遍历).
It's a little long. But If you go through it, you would figure out it plays a depth-first-traversal. Let's ignore the same route switching. Find ##### comment by e-cloud #####
and see the main procedure. It shows that it updates the canActivateChecks
first then performs next level travesal(Pre-order traversal at whole).
您必须知道路由器将应用程序的所有路由都视为url树.每个PreActivation
通过遍历将其future
(作为树路径)划分为路径段.
You must know the router treats all the routes of the app as a url tree. Each PreActivation
split its future
(as a tree path) into path segments by the traversal.
以一个简化示例为例:
我们的未来路线为
/a/b/c
.
然后我们将['/a','/a/b','/a/b/c']表示为canActivateChecks
we have the future route as
/a/b/c
.
Then we will get [ '/a', '/a/b', '/a/b/c' ] ascanActivateChecks
显然,canActivateChecks
表示从future
的顶部到最深处的路线
消息来源显示canActivateChecks
从左向右迭代.
Apparently, canActivateChecks
represents the routes from top to deepest of the future
The source shows canActivateChecks
is iterated from left to right.
我们可以得出结论,CanActivateChild
是从顶部到最深的孩子.
we can conclude that CanActivateChild
is run from top to deepest child.
希望我能清楚地解释它.
Hope i explain it clearly.
这篇关于警卫队,文档中的声明不明确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!