AngularJS – 访问子范围

如果我有以下控制器:

function parent($scope, service) { $scope.a = 'foo'; $scope.save = function() { service.save({ a: $scope.a, b: $scope.b }); } } function child($scope) { $scope.b = 'bar'; } 

parent读出child的正确方法是什么? 如果有必要在parent定义b ,假设b是一个描述与child有关的属性而不是parent的属性,那么这不会使它在语义上不正确吗?

更新:进一步思考,如果不止一个孩子有b它会为要检索的parent创build一个冲突。 我的问题仍然是,从parent获取b的正确方法是什么?

AngularJS中的范围使用原型inheritance,当在子范围内查找属性时,解释器将从子项开始查找原型链,继续到父项,直到find属性,而不是相反。

查看Vojta对此问题的评论https://groups.google.com/d/msg/angular/LDNz_TQQiNE/ygYrSvdI0A0J

简而言之:您无法从父作用域访问子作用域。

您的解决scheme

  1. 在父母中定义属性并从儿童访问它们(阅读上面的链接)
  2. 使用服务共享状态
  3. 通过事件传递数据。 $emit将事件向上发送给父节点,直到根作用域和$broadcast向下调度事件。 这可能会帮助你保持语义上的正确。

虽然jm的答案是处理这种情况的最佳方式,为了将来的参考,可以使用作用域的$$ childHead,$$ childTail,$$ nextSibling和$$ prevSibling成员来访问子作用域。 这些没有logging,所以他们可能会改变,恕不另行通知,但他们在那里,如果你真的需要遍历范围。

 // get $$childHead first and then iterate that scope's $$nextSiblings for(var cs = scope.$$childHead; cs; cs = cs.$$nextSibling) { // cs is child scope } 

小提琴

你可以试试这个:

 $scope.child = {} //declare it in parent controller (scope) 

然后在子控制器(范围)中添加:

 var parentScope = $scope.$parent; parentScope.child = $scope; 

现在父母可以访问孩子的范围。

一种可能的解决方法是使用init函数在父控制器中注入子控制器。

可能的实现:

 <div ng-controller="ParentController as parentCtrl"> ... <div ng-controller="ChildController as childCtrl" ng-init="ChildCtrl.init()"> ... </div> </div> 

ChildController你有:

 app.controller('ChildController', ['$scope', '$rootScope', function ($scope, $rootScope) { this.init = function() { $scope.parentCtrl.childCtrl = $scope.childCtrl; $scope.childCtrl.test = 'aaaa'; }; }]) 

所以现在在ParentController你可以使用:

 app.controller('ParentController', ['$scope', '$rootScope', 'service', function ($scope, $rootScope, service) { this.save = function() { service.save({ a: $scope.parentCtrl.ChildCtrl.test }); }; }]) 

重要:
要正常工作,你必须使用指令ng-controller并重新命名每个控制器使用像我在HTML例如。

提示:
在此过程中使用chrome插件ng-inspector 。 这将帮助你了解这棵树。

我不确定你是否“应该”从父母访问子范围,但是这是可能的。 我知道这是因为我自己做的。 这是我的情况:

我有一个函数,通过改变一个variables中的string来浏览我的页面。 那个variables在主index.html文件中被引用为ng-include。 所以,当string被改变时,一个新的html文件被加载到那个ng-include中。 在其中一个html文件中,我有另一个ng-include。 把这个视为第一个窗口内的一个小窗口。 每当我改变这些窗口中的内容,我也改变了一个侧面板的内容。 这个小组是在父母级别。 但是,当我进入父窗口内的较小窗口时,该父窗口侧面板中会有一些导航链接,它们在小窗口内进行切换。 由于侧面板处于父级别,小窗口的导航在子级别的自己的控制器中处理,所以当我点击侧面板上的链接时,必须编辑子控制器。 这可能是糟糕的编程。 老实说,我不知道。 几个月前我刚开始使用angularjs,而且我还在学习。 但是,为了使其适用于我的场景,我在父范围中创build了一个函数,在子范围加载时调用它:

 function parent($scope, service) { setCurrentChildController = function (childScope) { this.$scope.childScope = childScope; } } function child($scope) { scope.$parent.setCurrentChildController($scope); } 

所以,现在父作用域的variables$ scope.childScope本质上是子控制器的作用域。 它可以访问子范围内的所有variables和函数。 如果这是不好的编程,任何人都可以拿出一个替代解决scheme来解决这个问题。 但是,如果有必要的话,这是有用的

是的,我们可以将variables从子控制器分配给父控制器中的variables。 这是一个可能的方法:

概述:下面的代码的主要目标是将子控制器的$ scope.variable分配给父控制器的$ scope.assign

说明:有两个控制器。 在html中,请注意父控制器包含子控制器。 这意味着父控制器将在子控制器之前执行。 所以,第一个setValue()将被定义,然后控件将转到子控制器。 $ scope.variable将被分配为“child”。 然后这个子范围将作为parameter passing给父控制器的函数,其中$ scope.assign将得到值为“child”

 <!DOCTYPE html> <html> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script> <script type="text/javascript"> var app = angular.module('myApp',[]); app.controller('child',function($scope){ $scope.variable = "child"; $scope.$parent.setValue($scope); }); app.controller('parent',function($scope){ $scope.setValue = function(childscope) { $scope.assign = childscope.variable; } }); </script> <body ng-app="myApp"> <div ng-controller="parent"> <p>this is parent: {{assign}}</p> <div ng-controller="child"> <p>this is {{variable}}</p> </div> </div> </body> </html>