一尘不染

如何从Angular外部访问/更新$ rootScope

angularjs

我的应用程序在$ rootScope中初始化一个对象图,如下所示:

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

阅读 269

收藏
2020-07-04

共1个答案

一尘不染

除了非常少见的情况或调试目的外,这样做只是BAD的实践(或BAD应用程序设计的一种指示)!

对于非常罕见的情况(或调试),您可以这样进行:

  1. 访问您知道属于应用程序一部分的元素,并将其包装为jqLit​​e / jQuery元素。
  2. $rootScope通过访问获取元素的Scope,然后获取.scope().$root。(还有其他方法。)
  3. 尽您所能,但将其包装在中$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.debugInfoEnabled()

建议在生产中禁用调试信息(出于性能考虑),这意味着方法将不再起作用。

如果你只是想调试活动(生产)情况下,你可以调用
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 :(';
  });
}
2020-07-04