【问题标题】:angularjs: Change parent scope from controller within a ng-switchangularjs:从 ng-switch 中的控制器更改父范围
【发布时间】:2013-05-22 20:14:52
【问题描述】:

所以,我可以从子控制器更改模型值,但是当子控制器位于 ng-switch 时,它不起作用,为什么?我创建了an example 来演示它。

避免这种情况的一种方法是在模型名称中使用.,例如bunnies.kills。这是一个错误还是一个功能?

使用 Angular 1.0.6

【问题讨论】:

  • @sh0ber 是正确的。原因是ng-switch 创建了自己的范围。这意味着您确实有来自父级的两个嵌套级别的范围。

标签: javascript angularjs angularjs-scope angularjs-controller angularjs-ng-switch


【解决方案1】:

使用您的代码结构,您需要在子控制器中进行更改:

$scope.$parent.kills++;

$scope.$parent.$parent.kills++;

解释MainCtrl的作用域是SimpleParentCtrl的父作用域,却是Step1CtrlStep2Ctrl的祖父作用域。正如其他人指出的那样,ng-switch 创建了自己的范围,然后您的 Step1CtrlStep2Ctrl 分别创建了 ng-switch 的子范围。

注意:每次点击 1 或 2 按钮时,ng-switch 和它当前匹配的子控制器都会获得一个新的作用域。

另外:如果您碰巧正在查看 Angular 源代码并想知道 ng-switch 指令如何在没有 scope 属性的情况下创建自己的范围,答案是它是手动创建的通过scope.$new() 在其链接方法中。指令ng-includeng-switchng-repeatng-view 都以这种方式创建新作用域,无论是在链接方法中还是在编译方法返回的链接函数中。

资源:

https://github.com/angular/angular.js/wiki/The-Nuances-of-Scope-Prototypal-Inheritance http://www.youtube.com/watch?v=ZhfUv0spHCY&feature=youtu.be&t=30m

【讨论】:

    【解决方案2】:

    ng-switch 创建自己的子范围,这就是为什么@sh0ber 的答案是使其工作的一种方法。一般来说,models should be referenced 在控制器范围内(因此是引用对象),而不是不是原语。所以使用. 是“最佳实践”。

    这不是错误,但也不是功能。这就是JavaScript prototypal inheritance works 使用原语的方式。

    【讨论】:

    • 使用.?你能解释一下吗?
    • @chovy,当您在父作用域中创建对象时(或者更好的是,在父控制器中引用一个对象——例如,$scope.refToSomeOtherObj = MyService.someObj;),子作用域(这样的子作用域由ng-switch 指令)获取对该对象的引用。所以你可以直接引用子范围内的对象属性:$scope.refToSomeOtherObj.somePropertyOfSomeObj = ... 即,你不必使用$parent,这是一种脆弱的编码方式......如果你的控制器层次结构发生变化,$parent 可能不会不再工作了。
    【解决方案3】:

    我会采取稍微不同的方法来解决这个问题。

    而不是使用$scope.$parent,我建议你将所有的兔子杀戮逻辑转移到一个共享的服务/模型中。

    另外,我会尽量避免引用父视图/控制器。引用父级可能会使重用代码变得困难,并且随着项目的增长,调试起来会很痛苦。父母可以知道自己的孩子,但孩子应该对自己的父母知之甚少。

    这是更新的 Plunk:http://plnkr.co/edit/PLDbfU8Fu7m59A42qdR6?p=preview

    HTML

    <body ng-controller="MainCtrl">
        <p>
            Dead bunnies: <strong>{{Elmer.deadWabbits}}</strong>
        </p>
        <div ng-controller="SimpleParentCtrl">
            <button ng-click="Elmer.killTheWabbit()">Kill from simple parent gun</button>
        </div>
        <hr>
        <div ng-switch="" on="step">
            <div ng-switch-when="first" ng-controller="Step1Ctrl">
                <button ng-click="Elmer.killTheWabbit()">Kill from 1 tab gun</button>
            </div>
            <div ng-switch-when="second">
                <div ng-controller="Step2Ctrl">
                    <button ng-click="Elmer.killTheWabbit()">Kill from 2 tab gun</button>
                </div>
            </div>
        </div>
        <hr>
        <p>
            <button ng-click="changeStep('first')">1</button> <button ng-click="changeStep('second')">2</button>
        </p>
    </body>
    

    JS

    angular.module('plunker', []).
    service("Elmer", [function() {
        this.deadWabbits = 0;
        this.killTheWabbit = function() {
            this.deadWabbits++;
        };
    }]).
    controller('MainCtrl', function($scope, Elmer) {
      $scope.Elmer = Elmer;
      $scope.step = 'first';
      $scope.changeStep = function(name){
        $scope.step = name;
      };
    }).
    controller('SimpleParentCtrl', function() {}).
    controller('Step1Ctrl', function() {}).
    controller('Step2Ctrl', function() {});
    

    【讨论】:

    • 这是更好的方法,你说得对“孩子应该对它的父母一无所知”
    【解决方案4】:

    避免这种情况的一种方法是使用 .在模型名称中,例如 bunnies.kills。这是一个错误还是一个功能?

    这已经解释过很多次了:https://github.com/angular/angular.js/wiki/The-Nuances-of-Scope-Prototypal-Inheritance 在mhevery的视频中

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-02-22
      • 1970-01-01
      • 1970-01-01
      • 2015-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多