将在" n"上调用angular.bootstrap多个DOM节点,实例化" n" AngularJS应用程序?

时间:2015-10-05 17:23:22

标签: javascript angularjs dom

说调用angular.bootstrap会创建一个新的AngularJS实例,还有一个单独的摘要周期,根范围,注入器等等,这是正确的吗?

如果是这样,是否可以嵌套此类应用程序(即调用另一个AngularJS应用程序管理的DOM内DOM节点上的引导程序)? (我推测不!)

2 个答案:

答案 0 :(得分:1)

只有一个Angular实例。每个应用程序都有自己的注射器。而且,由于$rootScope是一项服务,这意味着每个应用程序都有自己的实例,反过来又有自己的摘要周期。

Bootstrapping涉及编译DOM,这意味着当您尝试引导它们时,已经编译了嵌套节点。

答案 1 :(得分:1)

它将创建Angular injector服务的新实例,该实例负责dependency injection并控制应用程序生命周期。因此,它还会创建应用程序中使用的服务的新实例(包括ng模块中的服务实例:$rootScope$compile等。

您可能会将其视为应用程序的新实例(模块集合)。 Angular本身(angular对象)没有被实例化。

angular.bootstrapangular.injector不同(后者只是创建一个新的注入器实例)是$rootElement通过angular.element(someElement).injector()服务到DOM元素的links an injector instance。这样,此元素及其子元素与特定的注入器实例相关联(可以使用angular.bootstrap(nestedAppElement, ['nestedApp']); angular.bootstrap(appElement, ['app']); 获取)。

无法在bootstrapped元素(或其子元素)上引导应用程序,Angular will protect it不会被搞砸。

然而,Angular并不是真正的万无一失,可以通过引导应用in reverse来完成:

app

看起来我们终于搞砸了。没有什么能阻止<nested-app-container>app中编译自己的指令,并且它使用自己的注入器和作用域(这里是element.data('$injector')根作用域)来编译它们,而不是属于它的作用域和注入器当前的DOM元素。如果嵌套的应用程序将被某些父app指令重新编译,那么事情会变得更加混乱。

绕过Angular万无一失的旁路进行双重自举是非常简单的。由于Angular使用inheritedData以分层方式获取元素的注入器(当在引导元素上未定义angular.module('app').directive('nestedAppContainer', function () { return { compile: function (element) { element.data('$injector', null); } }; }); 时,它会自动从父节点检索),它必须被覆盖:

app

现在应用can be safely bootstrapped in any order。但保持<nested-app-container>远离nestedAppContainer的问题仍然存在。它可以通过将angular.module('app').directive('nestedAppContainer', function () { return { priority: 100000, terminal: true, ... }; }); 指令标记为终端

来解决
nestedAppContainer = nestedAppContainer.createShadowRoot();

或将嵌套的应用程序放入shadow DOM

  <body>
    <div app-dir>
      <nested-app-container></nested-app-container>
    </div>
  </body>

专门用于隔离DOM部分(Chrome本身支持并在其他浏览器中填充)。

TL; DR:Angular中嵌套应用程序的解决方案

原来是shown here

var appElement = document.querySelector('body');

var nestedAppContainer = document.querySelector('nested-app-container');
// nestedAppContainer = nestedAppContainer.createShadowRoot();

var nestedAppElement = angular.element('<nested-app>')[0];
angular.element(nestedAppContainer).append(nestedAppElement);

angular.element(nestedAppElement)
  .append('<div app-dir>(app-dir)</div>')
  .append('<div nested-app-dir>(nested-app-dir)</div>');

angular.element().ready(function () {
  angular.bootstrap(appElement, ['app']);
  angular.bootstrap(nestedAppElement, ['nestedApp']);
});

angular.module('nestedApp', []).directive('nestedAppDir', function () {
  return {
    controller: function ($scope) {
      $scope.app = 'nested app';
    },
    compile: function (element) {
      element.prepend('nested app is "{{ app }}"');
    }
  }
});

angular.module('app', []).directive('appDir', function () {
  return {
    controller: function ($scope) {
      $scope.app = 'app';
    },
    compile: function (element) {
      element.prepend('app is "{{ app }}"');
    }
  }
});

angular.module('app').directive('nestedAppContainer', function () {
  return {
    priority: 100000,
    // 'terminal' is redundant with nestedAppContainer.createShadowRoot()
    terminal: true,
    compile: function (element) {
      // element injector is not 'undefined' anymore,
      // so it won't be inherited from parent elements
      element.data('$injector', null);
    }
  };
});

<a class="example-image-link" href="images/image-1.jpg" data-lightbox="example-1"><img class="example-image" src="images/thumb-1.jpg" alt="Girl looking out people on beach"></a>

虽然看起来很整洁,但要小心。正如任何其他攻击无证件的黑客一样,这个可能会隐藏不良副作用或被新框架释放打破。

没有那么多可能需要黑客攻击的案例。大多数时候你都有冲动框架的冲动,你做错了。