将调用angular.bootstrap上" N"多个DOM节点,实例和QUOT; N" AngularJS应用程序? [英] Will invoking angular.bootstrap on "n" multiple DOM nodes, instantiate "n "AngularJS applications?

查看:203
本文介绍了将调用angular.bootstrap上" N"多个DOM节点,实例和QUOT; N" AngularJS应用程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是不是正确的说,调用 angular.bootstrap 将创建AngularJS的新实例,加上一个独立的消化周期,根范围内,喷油器等<? / p>

如果是这样,就可以嵌套这样的应用程序(即调用引导对DOM节点由另一AngularJS应用管理的DOM中)? (我presume没有!)


解决方案

这将创建角的喷油器服务,这是负责依赖注入并控制应用生命周期。因此,它也产生这是在应用程序(包括的那些纳克模块使用的服务的新实例: $ rootScope $编译等)。

您可以把它作为应用程序(这是模块的集合)的一个新的实例。角本身()对象不是实例。

这是不同的事情 angular.bootstrap angular.injector (后者刚刚创建一个新的喷油器实例)是它链接注射器实例通过 $ rootElement的服务手段DOM元素。这样,这个元素和它的孩子们与特定的喷油器实例相关联。

(它可以与 angular.element(someElement).injector()收购)

这是不可能的引导自举元素(或子女)上的应用程序,角的将防止它被搞砸的。

然而,角是不是真的防呆,它可以通过自举应用程序的反向

  angular.bootstrap(nestedAppElement,['nestedApp']);
angular.bootstrap(appElement,['应用']);

看起来我们终于搞砸的事情了。没有prevents 应用在编制自己的指令&LT;嵌套应用程序容器&GT; ,它使用自己的喷油器和范围(这里是应用根范围内)来编译他们,而不是范围和喷油器属于目前的DOM元素。如果嵌套应用程序会被一些家长的应用程序指令重新编译的事情会变得更加杂乱。

绕过角防呆旁路双引导是非常简单的。由于角使用 inheritedData 获得元素的注入在分层方式(当 element.data('$喷油器')未定义自举元素,它会自动从父母检索)上,它必须被覆盖:

  angular.module(应用)。指令(nestedAppContainer',函数(){
  返回{
    编译:函数(元素){
      element.data('$喷油器',NULL);
    }
  };
});

现在的应用可以安全地在任何订单自举。但随着保持应用远离&LT的问题;嵌套应用程序容器&GT; 仍然存在。它可以解决任何带标记 nestedAppContainer 指令作为终端

  angular.module(应用)。指令(nestedAppContainer',函数(){
  返回{
    优先级:100000,
    终端:真实,
    ...
  };
});

或将嵌套应用到影子DOM

  nestedAppContainer = nestedAppContainer.createShadowRoot();

这是专门用来隔离DOM部分(由Chrome本身支持和其他浏览器polyfilled)。


TL; DR:解决嵌套应用中的角

由于它是这里图所示:

 &LT;身体GT;
    &LT; D​​IV APP-DIR&GT;
      &LT;嵌套应用程序容器&GT;&LT; /嵌套应用程序容器&GT;
    &LT; / DIV&GT;
  &LT; /身体GT;

  VAR appElement = document.querySelector('身体');VAR nestedAppContainer = document.querySelector('嵌套应用容器');
// nestedAppContainer = nestedAppContainer.createShadowRoot();VAR nestedAppElement = angular.element('&LT;嵌套应用&GT;')[0];
angular.element(nestedAppContainer).append(nestedAppElement);angular.element(nestedAppElement)
  .append('&LT; D​​IV APP-DIR&GT;(APP-DIR)LT; / DIV&GT;')
  .append('&LT; D​​IV嵌套应用-DIR&GT;(嵌套-APP-DIR)LT; / DIV&GT;');angular.element()。就绪(函数(){
  angular.bootstrap(appElement,['应用']);
  angular.bootstrap(nestedAppElement,['nestedApp']);
});angular.module('nestedApp',[])。指令(nestedAppDir',函数(){
  返回{
    控制器:函数($范围){
      $ scope.app ='嵌套应用;
    },
    编译:函数(元素){
      。元素prePEND('嵌套程序是{{应用}}');
    }
  }
});angular.module('应用',[])。指令(APPDIR',函数(){
  返回{
    控制器:函数($范围){
      $ scope.app =应用;
    },
    编译:函数(元素){
      。元素prePEND('程序是{{应用}}');
    }
  }
});angular.module(应用)。指令(nestedAppContainer',函数(){
  返回{
    优先级:100000,
    //'终端'是多余的nestedAppContainer.createShadowRoot()
    终端:真实,
    编译:函数(元素){
      //元素注入是不是未定义了,
      //所以它不会从父元素继承
      element.data('$喷油器',NULL);
    }
  };
});

虽然它可能看起来很整齐,审慎行事。作为一种利用未公开的东西,任何其他黑客,这其中可能隐藏不良副作用或新的框架版本被打破。

有没有这么多的情况下,这可能是需要的黑客。你有一个冲动打的框架大多数时候,你这样做是错误的。

Is it correct to say that invoking angular.bootstrap will create a new instance of AngularJS, together with a separate digest cycle, root scope, injector and so on?

If so, is it possible to nest such applications (i.e. invoke bootstrap on DOM nodes inside the DOM managed by another AngularJS app)? (I presume no!)

解决方案

It will create a new instance of Angular injector service, which is responsible for dependency injection and controls application life cycle. Consequently, it also creates new instances of the services which are used in the application (including the ones from ng module: $rootScope, $compile, etc).

You may think of it as of a new instance of the application (which is the collection of modules). Angular itself (angular object) isn't instantiated.

The thing that differs angular.bootstrap from angular.injector (the latter just creates a new injector instance) is that it links an injector instance to DOM element by means of $rootElement service. This way this element and its children are associated with specific injector instance (it can be acquired with angular.element(someElement).injector()).

It is not possible to bootstrap an app on bootstrapped element (or its children), Angular will protect it from being messed up.

However, Angular is not really fool-proof, it can be done by bootstrapping the apps in reverse:

angular.bootstrap(nestedAppElement, ['nestedApp']);
angular.bootstrap(appElement, ['app']);

Looks like we finally messed the things up. Nothing prevents app from compiling its own directives in <nested-app-container>, and it uses its own injector and scope (it is app root scope here) to compile them, not scope and injector that belong to current DOM element. And the things will become even more messy if nested app will be re-compiled by some parent app directive.

Bypassing Angular fool-proof bypass for double bootstrapping is quite straightforward. Since Angular uses inheritedData to get element's injector in hierarchical manner (when element.data('$injector') is undefined on bootstrapped element, it is automatically retrieved from parents), it has to be overwritten:

angular.module('app').directive('nestedAppContainer', function () {
  return {
    compile: function (element) {
      element.data('$injector', null);
    }
  };
});

Now the apps can be safely bootstrapped in any order. But the problem with keeping app away from <nested-app-container> is still there. It can be solved either with marking nestedAppContainer directive as terminal

angular.module('app').directive('nestedAppContainer', function () {
  return {
    priority: 100000,
    terminal: true,
    ...
  };
});

or by putting nested app into shadow DOM

nestedAppContainer = nestedAppContainer.createShadowRoot();

which is specifically intended to isolate DOM parts (natively supported by Chrome and polyfilled in other browsers).


TL;DR: the solution to nested apps in Angular

As it is shown here:

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

and

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);
    }
  };
});

While it may look quite neat, proceed with care. As any other hack that exploits undocumented stuff, this one may conceal adverse side-effects or be broken by new framework release.

There are not so many cases that may be in need of hacks. Most times you have an urge to fight the framework, you're doing it wrong.

这篇关于将调用angular.bootstrap上&QUOT; N&QUOT;多个DOM节点,实例和QUOT; N&QUOT; AngularJS应用程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆