【问题标题】:AngularJS model introspection/reflectionAngularJS 模型自省/反射
【发布时间】:2014-06-25 19:07:33
【问题描述】:

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

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

【问题讨论】:

标签: angularjs reflection batarang


【解决方案1】:

找到方法了,这里有一段代码可以改变 Angular 之外的范围:

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

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

【讨论】:

  • 而不是像 Michał Dudak 在他的回答中所写的角度元素,您可以使用 jQuery $('.section:eq(0)').scope();
【解决方案2】:

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

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

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

【讨论】:

  • 很高兴知道您可以使用 jquery 来获取元素而不是 angular.element 并使用范围作为插件。但是您可以遍历范围 - 阅读@ExpertSystem 答案。
  • @jcubic:关于您对 jQuery 的评论:.scope() 是一种特定于 Angular 的方法。如果你同时包含 jQuery 和 Angular(jQuery 脚本必须在 AngularJS 之前),那么 angular.element()$() 的别名,所以你可以用前者做的任何事情也可以用后者做。如果 jQuery 不存在(或者它在 AngularJS 之后加载),那么angular.element()“回退”到使用集成的“轻量级”版本的 jQuery (jqLit​​e)。
【解决方案3】:

1.访问/修改范围属性

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


2。让 Angular 知道

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


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

例如要遍历整个作用域树,可以使用以下 sn-p:

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

【讨论】:

  • 谢谢,现在我可以为 Angular 创建模型自省操作工具了。
  • @jcubic:你可能已经知道了,但是 Batarang 是开源的,所以无论如何它都是一个不错的起点。
  • 它不允许更改范围,所以我认为这不是我想要的,还需要刷新浏览器才能看到范围,所以我认为它修改了 Angular 应用程序或Angular 本身是为了查看模型。也许我只是 fork Ba​​tarang 并添加允许修改范围的功能。
  • 是的,我就是这个意思。我知道它并不能完全满足您的要求,但它似乎解决了部分问题,所以它的一部分应该作为起点有用(为了不重新发明轮子)。
  • 我编写了一个名为 AngScope 的小 Firebug 插件,可以帮助您检查 $scope 对象。它在 Firebug 的 DOM 检查器中显示它们。从那里您可以选择要在控制台中使用的对象,编辑属性并调用$apply()
猜你喜欢
  • 1970-01-01
  • 2011-01-03
  • 1970-01-01
  • 2016-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-09
  • 2012-05-07
相关资源
最近更新 更多