本文介绍了Angular Guards,文档中的声明不清楚的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图深入了解 angular,所以我阅读了文档,这很有帮助.
现在我正在研究守卫.我在文档中阅读了此声明.

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 守卫,直到最深的子路由.

现在我很困惑,为什么 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?

推荐答案

我曾试图相信文档站点中所写的内容.但是,它似乎并不完全正确,或者实现已更新但文档未更新.

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;博士

我们应该检查源代码,看看它是如何工作的.

we should check the source to see how it work.

注意:检查的提交是:https://github.com/angular/angular/tree/edb8375a5ff15d77709ccf1759efb14091fa86a4

步骤 1 - 查看 CanActivateChild 何时被调用

在此处获取 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.

L926 和 L950.

runCanActivateChildcanActivateChecks 的迭代中被调用,与 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);
      }
    }
  }

有点长.但是如果你仔细研究它,你会发现它是一个深度优先遍历.让我们忽略相同的路由切换.找到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).

你要知道路由器把app的所有路由当成一个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

显然,canActivateChecks 代表了未来从顶部到最深处的路线源代码显示 canActivateChecks 从左到右迭代.

Apparently, canActivateChecks represents the routes from top to deepest of the futureThe source shows canActivateChecks is iterated from left to right.

我们可以得出结论,CanActivateChild 从顶部到最深的孩子运行.

we can conclude that CanActivateChild is run from top to deepest child.

希望我解释清楚.

这篇关于Angular Guards,文档中的声明不清楚的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-30 00:16