112

如果我有以下控制器:

function parent($scope, service) {
    $scope.a = 'foo';

    $scope.save = function() {
        service.save({
            a:  $scope.a,
            b:  $scope.b
        });
    }
}

function child($scope) {
    $scope.b = 'bar';
}

什么是让parentread bout的正确方法child?如果有必要定义bin ,假设它是一个描述与而不是相关的东西的属性,parent这不会使它在语义上不正确吗?bchildparent

更新:进一步想一想,如果有多个孩子b,就会产生冲突,parent以求b取回。b我的问题仍然存在,从访问的正确方法是parent什么?

4

6 回答 6

163

AngularJS 中的作用域使用原型继承,当在子作用域中查找属性时,解释器将从子作用域开始查找原型链并继续到父作用域,直到找到该属性,而不是相反。

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

简而言之:您不能从父范围访问子范围。

您的解决方案:

  1. 在父级中定义属性并从子级访问它们(阅读上面的链接)
  2. 使用服务共享状态
  3. 通过事件传递数据。$emit将事件向上发送到父级,直到根范围并向$broadcast下调度事件。这可能会帮助您保持语义正确。
于 2012-11-17T06:11:37.213 回答
83

虽然 jm- 的答案是处理这种情况的最佳方式,但为了将来参考,可以使用范围的 $$childHead、$$childTail、$$nextSibling 和 $$prevSibling 成员访问子范围。这些没有记录,因此它们可能会在没有通知的情况下更改,但如果您确实需要遍历范围,它们就在那里。

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

小提琴

于 2013-05-31T09:00:48.583 回答
49

你可以试试这个:

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

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

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

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

于 2015-02-06T20:25:41.617 回答
4

一种可能的解决方法是使用 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并重命名每个控制器,as就像我在 html 中所做的那样,例如。

提示:在此过程中
使用 chrome 插件ng-inspector 。它将帮助您理解树。

于 2015-07-03T03:26:04.677 回答
3

使用$emit$broadcast,(如 walv 在上面的评论中提到的)

向上触发事件(从子到父)

$scope.$emit('myTestEvent', 'Data to send');

向下触发事件(从父级到子级)

$scope.$broadcast('myTestEvent', {
  someProp: 'Sending you some data'
});

最后听

$scope.$on('myTestEvent', function (event, data) {
  console.log(data);
});

有关更多详细信息:- https://toddmotto.com/all-about-angulars-emit-broadcast-on-publish-subscribing/

享受 :)

于 2019-02-12T15:01:19.850 回答
2

是的,我们可以将子控制器中的变量分配给父控制器中的变量。这是一种可能的方式:

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

解释:有两个控制器。在 html 中,请注意父控制器包含子控制器。这意味着父控制器将在子控制器之前执行。因此,首先将定义 setValue(),然后将控件转到子控制器。$scope.variable 将被分配为“孩子”。然后这个子作用域将作为参数传递给父控制器的函数,其中 $scope.assign 将获取值作为“子”

<!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>
于 2017-09-07T14:23:08.203 回答