我的应用程序初始化$rootScope中的对象图,如下。。。
var myApp = angular.module('myApp', []);
myApp.run(function ($rootScope) {
$rootScope.myObject = { value: 1 };
});
然后消耗对象图中的数据(仅单向绑定(,如下所示。。。
<p>The value is: {{myObject.value}}</p>
这很好,但如果我随后(在页面渲染完成后(尝试更新$rootScope并用新对象替换原始对象,它将被忽略。我最初认为这是因为AngularJS保留了对原始对象的引用,尽管我已经替换了它
然而,如果我在控制器中包装使用HTML,我就能够以预期的方式重复更新其范围,并且修改会正确地反映在页面中。
myApp.controller('MyController', function ($scope, $timeout) {
$scope.myObject = { value: 3 };
$timeout(function() {
$scope.myObject = { value: 4 };
$timeout(function () {
$scope.myObject = { value: 5 };
}, 1000);
}, 1000);
});
有没有任何方法可以通过$rootScope实现这一点,或者只能在控制器内完成?此外,是否有更推荐的模式来实施此类操作?具体来说,我需要一种方法来替换AngularJS在AngularJS代码之外使用的完整对象图。
提前感谢您的建议,Tim
编辑:正如评论中所建议的,我已经尝试在$apply中执行更改,但没有帮助:
setTimeout(function() {
var injector = angular.injector(["ng", "myApp"]);
var rootScope = injector.get("$rootScope");
rootScope.$apply(function () {
rootScope.myObject = { value: 6 };
});
console.log("rootScope updated");
}, 5000);
除了非常非常罕见的情况或调试目的外,这样做只是糟糕的实践(或表明应用程序设计糟糕(
对于非常非常罕见的情况(或调试(,您可以这样做:
- 访问您知道是应用程序一部分的元素,并将其包装为jqLite/jQuery元素
- 通过访问
.scope().$root
获取元素的Scope,然后获取$rootScope
。(还有其他方法。( - 做任何你做的事情,但把它包在
$rootScope.$apply()
中,这样Angular就会知道发生了什么,并发挥它的魔力
例如:
function badPractice() {
var $body = angular.element(document.body); // 1
var $rootScope = $body.scope().$root; // 2
$rootScope.$apply(function () { // 3
$rootScope.someText = 'This is BAD practice :(';
});
}
另请参阅简短演示。
编辑
Angular 1.3.x引入了一个选项,禁止调试信息附加到DOM元素(包括scope
(:$compileProvider.debuginInfoEnabled((
建议在生产中禁用调试信息(为了性能(,这意味着上述方法将不再工作。
如果您只想调试一个实时(生产(实例,您可以调用angular.reloadWithDebugInfo((,它将在启用调试信息的情况下重新加载页面。
或者,您可以使用Plan B(通过元素的注入器访问$rootScope
(:
function badPracticePlanB() {
var $body = angular.element(document.body); // 1
var $rootScope = $body.injector().get('$rootScope'); // 2b
$rootScope.$apply(function () { // 3
$rootScope.someText = 'This is BAD practice too :(';
});
}
更新$rootScope后,调用$rootScope$apply((来更新绑定。
将修改作用域视为一个原子操作,$apply((提交这些更改。
如果要更新根作用域的对象,请将$rootScope
注入控制器:
myApp.controller('MyController', function ($scope, $timeout, $rootScope) {
$rootScope.myObject = { value: 3 };
$timeout(function() {
$rootScope.myObject = { value: 4 };
$timeout(function () {
$rootScope.myObject = { value: 5 };
}, 1000);
}, 1000);
});
演示小提琴