Подтвердить что ты не робот

Angular защита, неясное утверждение в документах

Я пытаюсь понять angular глубоко, поэтому я прочитал документы, и это было очень полезно.
теперь я изучаю охранников. и я прочитал это выражение в документах.

Маршрутизатор сначала проверяет защиту CanDeactivate и CanActivateChild, начиная с самого глубокого дочернего маршрута до вершины. Затем он проверяет защитные устройства CanActivate сверху вниз на самый глубокий дочерний маршрут.

теперь я в замешательстве, почему angular выполняет его таким образом?
есть ли какие-либо преимущества при проверке от самого глубокого ребенка до вершины для CanDeactivate и CanActivateChild. и сверху до самого детского маршрута для CanActivate?

4b9b3361

Ответ 1

Я пытался поверить в то, что написано на сайте docs. Тем не менее, кажется, что это не совсем правильно, или реализация была обновлена, но документы не обновляются.

Чтобы быть кратким:

Во-первых, защита CanDeactivate проверяется от самого глубокого до верхнего уровня и CanActivate проверяется защита сверху до глубины (она будет выйти с ложной проверкой обхода).

Во-вторых, защита CanActivateChild не проверяется с глубины доверху.


TL; DR

Подробное описание

мы должны проверить источник, чтобы узнать, как он работает.

Примечание. Проверенная фиксация: https://github.com/angular/angular/tree/edb8375a5ff15d77709ccf1759efb14091fa86a4

шаг 1 - см., когда CanActivateChild получил вызов

источник здесь L929.

Это только место, которое вызывал его главный вызывающий абонент runCanActivateChild.

В этой строке мы можем получить некоторый намек на то, что он делает тот же трюк, что и CanActivate, потому что CanActivate старший вызывающий runCanActivate вызывается после.

шаг 2 - посмотрите, как работает runCanActivateChild

L926 и L950.

runCanActivateChild вызывается внутри итерации canActivateChecks, так же, как и вызываемый runCanActivate. Здесь мы знаем CanActivate (я имею в виду функцию) и CanActivateChild используют один и тот же источник данных - canActivateChecks.

шаг 3 - что такое canActivateChecks и как он обрабатывается

Итак, что такое canActivateChecks? Очевидно, мы можем найти массив массивов экземпляров класса CanActivate. Но как назначить canActivateChecks? Перейдите сюда 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, затем выполняет траверс следующего уровня (обход предварительного порядка в целом).

Вы должны знать, что маршрутизатор рассматривает все маршруты приложения как дерево URL-адресов. Каждый PreActivation разбивает свой future (как путь к дереву) на сегменты пути путем обхода.

Возьмите упрощенный пример:

у нас есть будущий маршрут как /a/b/c.
Тогда мы получим ['/a', '/a/b', '/a/b/c'] как canActivateChecks

По-видимому, canActivateChecks представляет маршруты от вершины до самой глубины future Источник показывает, что canActivateChecks повторяется слева направо.

шаг 4 - заключение

мы можем заключить, что CanActivateChild выполняется от вершины до самого глубокого.

Надеюсь, я объясню это ясно.

Ответ 2

Когда вы думаете о маршрутизации, чем глубже в дерево вы идете, тем более конкретным вы получите.

Например:

/food-types/sweets/pies/blueberry

Поэтому, когда вы указываете Angular, вы хотите перейти от пирога blueberry, сначала он проверяет CanDeactivate на чернике, потому что вы возвращаетесь к дереву навигации в другое место. CanActivateChild также подойдет к дереву к дочернему пути, по моему пониманию, по той же причине: сначала он хочет проверить самые глубокие уровни, чтобы убедиться, что их дети могут быть активированы.

Обратное верно для CanActivate. Когда вы скажете Angular, вы хотите увидеть пирог blueberry, вы идете по дереву, и, таким образом, он проверяет охрану так, как она идет по дереву.