var myApp = angular.module('myApp',[]); myApp.run(function ($rootScope) { $rootScope.myObject = { value: 1 }; });
…然后从该对象图表消耗数据(仅限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代码外部消耗的完整对象图。
感谢您提出建议,
蒂姆
编辑:如评论中建议,我已经尝试执行$ 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,dude ! :('; }); }
另见,short demo。
编辑
Angular 1.3.x引入了一个选项来禁用调试信息附加到DOM元素(包括范围):$compileProvider.debugInfoEnabled()
建议在生产中禁用调试信息(出于性能考虑),这意味着上述方法将不再工作。
如果你只想调试一个实时(生产)实例,你可以调用angular.reloadWithDebugInfo(),它将重新加载启用了调试信息的页面。
或者,您可以使用计划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,dude ! :('; }); }