首页 文章

角卫,文档中的陈述不清楚

提问于
浏览
23

我正在努力深入了解角度,所以我读了the docs,这非常有帮助 .
现在我正在研究守卫 . 我在文档中读到了这个陈述 .

路由器首先检查CanDeactivate和CanActivateChild防护,从最深的子路径到顶部 . 然后它从上到下检查CanActivate警卫到最深的子路线 .

现在我很困惑,为什么角度以这种方式执行它?
对于 CanDeactivateCanActivateChild ,从最深的孩子到顶部进行检查有什么好处 . CanActivate 从顶部到最深的儿童路线?

2 回答

  • 4

    我试图相信文档网站上写的内容 . 但是,它似乎并不完全正确,或者实施已更新,但文档不会更新 .

    To be Brief:

    首先,从最深到最顶层检查 CanDeactivate 防护装置,并从顶部到最深处检查 CanActivate 防护装置(它将在遍历中进行错误检查) .

    其次, CanActivateChild 警卫不会从最深处检查到顶部 .


    TL; DR

    详细说明

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

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

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

    source here L929 .

    这只是它的优秀来电者被叫到的地方 .

    在那一行,我们可以得到一些暗示它与 CanActivate 做同样的技巧,因为 CanActivate 的高级调用者 runCanActivate 被称为 .

    第2步 - 看看runCanActivateChild是如何工作的

    L926L950 .

    runCanActivateChildcanActivateChecks 的迭代中被调用,与调用 runCanActivate 的方式相同 . 在这里,我们知道 CanActivate (我的意思是该功能)和 CanActivateChild 共享相同的数据源 - canActivateChecks .

    第3步 - 什么是canActivateChecks以及如何处理它

    那么, canActivateChecks 是什么?显然,我们可以发现它是一个 CanActivate 类实例的数组 . 但是如何分配 canActivateChecksGo 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, 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 ##### 并查看主要程序 . 它显示它首先更新 canActivateChecks 然后执行下一级别的travesal(整个预订遍历) .

    您必须知道路由器将应用程序的所有路由视为URL树 . 每个 PreActivation 通过遍历将其 future (作为树路径)分割为 path segments .

    simplified 示例:

    我们的未来路线为/ a / b / c . 然后我们将获得['/ a','/ a / b','/ a / b / c']作为canActivateChecks

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

    第4步 - 结论

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

    希望我能清楚地解释清楚 .

  • 14

    当你考虑路由时,你走的树越深,你得到的就越具体 .

    例如:

    /food-types/sweets/pies/blueberry

    因此,当您告诉Angular您希望远离 blueberry 饼时,它首先会检查蓝莓上的 CanDeactivate ,因为您正在向上返回导航树,到另一个位置 . 根据我的理解, CanActivateChild 也会走到树的路径上,出于同样的原因:它想先检查最深层次,以验证他们的孩子是否可以被激活 .

    反之亦然 CanActivate . 当你告诉Angular你想要看到 blueberry 饼时,你正沿着树走下去,因此,当它沿着树走下去时,它会按顺序检查守卫 .

相关问题