说调用angular.bootstrap
会创建一个新的AngularJS实例,还有一个单独的摘要周期,根范围,注入器等等,这是正确的吗?
如果是这样,是否可以嵌套此类应用程序(即调用另一个AngularJS应用程序管理的DOM内DOM节点上的引导程序)? (我推测不!)
答案 0 :(得分:1)
只有一个Angular实例。每个应用程序都有自己的注射器。而且,由于$rootScope
是一项服务,这意味着每个应用程序都有自己的实例,反过来又有自己的摘要周期。
Bootstrapping涉及编译DOM,这意味着当您尝试引导它们时,已经编译了嵌套节点。
答案 1 :(得分:1)
它将创建Angular injector服务的新实例,该实例负责dependency injection并控制应用程序生命周期。因此,它还会创建应用程序中使用的服务的新实例(包括ng
模块中的服务实例:$rootScope
,$compile
等。
您可能会将其视为应用程序的新实例(模块集合)。 Angular本身(angular
对象)没有被实例化。
angular.bootstrap
与angular.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本身支持并在其他浏览器中填充)。
原来是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>
虽然看起来很整洁,但要小心。正如任何其他攻击无证件的黑客一样,这个可能会隐藏不良副作用或被新框架释放打破。
没有那么多可能需要黑客攻击的案例。大多数时候你都有冲动框架的冲动,你做错了。