3

是否可以在 Angular 应用程序中内省/反映模型,您可以在其中更改范围并遍历它?像batarang这样的东西有,但这将允许改变价值观。

如果不是,是否可以对 Angular 代码进行猴子补丁(通过在页面上包含另一个脚本)使其成为可能?

4

3 回答 3

3

1.访问/修改范围属性

Angular 的$scope对象是普通的旧 JS 对象,因此可以通过标准方式进行操作。
例如someScope.someProp,检索属性的值,同时someScope.someProp = someValue设置属性的值。


2. 让 Angular 知道

修改对象的属性是一回事——让 Angular 意识到变化是另一回事。Angular 在运行一个循环
之前不会知道我们的修改。$digest如果我们想立即应用更改,我们可以显式地触发一个$digest循环,使用someScope.$apply().


3. 把握范围

为了获得对与 DOM 元素关联的范围的引用,我们需要对相应的 DOM Node 对象具有引用,将其包装angular.element并执行其scope()方法。
像这样的东西:

<body class="ng-scope">

var someScope = angular.element(document.body).scope();

此外,如果我们想访问$rootScope(所有作用域的父作用域),我们可以使用注入器来注入$rootScope服务:

<html ng-app="myApp">

var injector = angular.element(document.documentElement).injector();
var rootScope = injector.get('$rootScope');

4. 遍历范围树

一旦我们掌握了一个作用域对象,我们可能想要遍历作用域树。每个范围都具有以下属性(除其他外):

  • $parent:此范围的父范围(如果有)。
  • $$nextSibling:此范围的下一个兄弟范围(如果有)。
    (同级作用域是具有相同的作用域$parent
  • $$childHead:此范围的第一个子范围(如果有)。

为了以someScope根为根遍历范围树的分支:

var scopes = [someScope];
while (scopes.length) {
    var scope = scopes.shift();
    console.log(scope);
    if (scope.$$nextSibling) { scopes.unshift(scope.$$nextSibling); }
    if (scope.$$childHead) { scopes.unshift(scope.$$childHead); }
}

例如,要遍历整个作用域树,您可以使用以下代码段:

var injector = angular.element(document.body).injector();
var rootScope = injector.get('$rootScope');

var scopes = [rootScope];
while (scopes.length) {
    var scope = scopes.shift();
    report(scope);
    if (scope.$$nextSibling) { scopes.unshift(scope.$$nextSibling); }
    if (scope.$$childHead) { scopes.unshift(scope.$$childHead); }
}

function report(scope) {
    var str = '' + scope.$id;

    while (scope.$parent) {
        str = scope.$parent.$id + ' => ' + str;
        scope = scope.$parent;
    }

    console.log(str);
}
于 2014-05-12T21:24:14.077 回答
1

找到了方法,这是一个更改 Angular 之外范围的代码:

var $scope = angular.element($('.section:eq(0)')).scope();
$scope.$apply(function() {
   scope.color = "blue";
});

angular.element().scope()返回范围并且可以进行调查。不确定如何遍历范围树,但这是一个很好的起点。如果没有范围遍历,您可以只遍历 DOM 并检查该 DOM 元素上是否有新的范围。

于 2014-05-12T13:58:17.377 回答
1

您可以通过调用由(或者,如果您还使用 jQuery)scope()返回的对象上的方法来获取范围,例如. 没有直接访问子作用域的方法。但是知道所有具有与其关联的新范围的元素都具有该类,您可以改为遍历元素树。angular.element()$()angular.element(".foo").scope()ng-scope

$(".foo").find(".ng-scope").each(function() {
  var scope = $(this).scope();
});

然而,这可能有点棘手,因为find()将在下面找到所有节点.foo,无论它们的深度如何。您可以children()改用,但它可能不会产生任何结果,因为 的直接后代.foo可能不会创建新范围。

于 2014-05-12T17:53:24.183 回答