AngularJS控制器继承

Pra*_*dar 28 angularjs angularjs-scope

AngularJS具有基于DOM的控制器继承,如角度文档中所述.

<div ng-controller="BaseController">
    <p>Base Controller Value: {{value}}</p>
    <button ng-click="updateValue()">Update In Base</button>
    <div ng-controller="DerivedController">
        <p>Derived Controller Value: {{value}}</p>
        <button ng-click="updateValue()">Update In Derived</button>
    </div>
</div>
Run Code Online (Sandbox Code Playgroud)

范围变量"value"仅出现在BaseController中.基于此,在BaseController或DerivedController中更改方法的值时,我希望两个值都需要更新.但只有单个范围变量才会更新.

这是一个演示相同示例的小提琴:http://jsfiddle.net/6df6S/1/

如何在一个级别上进行更改以传播到当前作用域的直接子级和直接父级.

我们可以通过使用实现这一点

$范围.$腕表

没有使用它或任何这样的观察者,有没有办法做到这一点?

编辑1:

通过使用$ scope.$ watch这就是我的意思

$scope.$watch("value", function () {
   $scope.$broadcast("childChangeListener"); //Downwards to all children scopes
   $scope.$emit("parentChangeListener"); //Upwards to all parent scopes
});
Run Code Online (Sandbox Code Playgroud)

我一直在寻找在不使用这种机制的情况下在所有范围内更新值的方法.

Mar*_*cok 50

当多个控制器需要访问相同的数据时,应使用服务.您不应该依赖范围继承,因为它限制了您编写HTML的方式.例如,在将来,您决定DerivedController不应该是BaseController的子代.

您的服务通常应提供公共API,并隐藏实现.这使得重构内部更容易.

HTML:

<div ng-controller="BaseController">
    <p>Base Controller Value: {{model.getValue()}}</p>
    <button ng-click="model.updateValue('Value updated from Base')">Update In Base</button>
    <div ng-controller="DerivedController">
        <p>Derived Controller Value: {{model.getValue()}}</p>
        <button ng-click="model.updateValue('Value updated from Derived')">Update In Derived</button>
    </div>
</div>
Run Code Online (Sandbox Code Playgroud)

JavaScript的:

app.factory('sharedModel', function () {
    // private stuff
    var model = {
        value: "initial Value"
    };
    // public API
    return {
        getValue:    function() { 
           return model.value; 
        },
        updateValue: function(value) {
           model.value = value;
        }
    };
});

function BaseController($scope, sharedModel) {
    $scope.model = sharedModel;
}

function DerivedController($scope, sharedModel) {
    $scope.model = sharedModel;
}
Run Code Online (Sandbox Code Playgroud)

小提琴.

另外,我不建议使用$ rootScope在控制器之间共享.


小智 8

小提琴中的绑定直接在范围内的属性上.您需要的继承可以通过在作用域中的对象上绑定数据来实现.

http://jsfiddle.net/2Dtyq/

scope.shared = {}    
scope.shared.value = "Something"
Run Code Online (Sandbox Code Playgroud)

而不仅仅是

scope.value= "Something"
Run Code Online (Sandbox Code Playgroud)

怎么了?
构造DerivedController时,原型传递的作用域继承自BaseController的作用域.
DerivedController的范围对象仍然没有自己的属性"value".因此它仍然绑定了从父母范围获得的属性.
现在,如果单击" 在基础更新"按钮,它将反映在两个绑定中.单击"在派生更新"按钮时,将在DerviedController的范围上创建名为"value"的新属性.因此,对父级的value属性的绑定被破坏.对Update In Base的任何更多点击都不会刷新第二个数据绑定.
将其放在单独的对象中会阻止创建新属性,因此仍然保留继承.


Cha*_*ani 5

您不能直接引用子控制器中的字符串值.由于原型继承设置value子范围(在使用子控制器时创建)的属性在子范围上创建该属性,而不是更新父范围属性.

您的范围不是模型,因此我们应该避免$scope使用大量属性污染变量.创建模型对象并在其上创建子属性.然后,可以沿子控制器\ scope传递此对象.

我修改了你的jsfiddle以解释上述观点.

此外,我强烈建议您浏览此Wiki页面,以了解原型继承的麻烦.

  • +1,但我建议使用服务在控制器之间共享数据,而不是依赖某个HTML结构来提供范围继承(请参阅我的回答). (2认同)

Bru*_*uno 2

看一下$broadcast方法。引用文档:

向下分派事件名称到所有子作用域(及其子作用域),通知注册的 ng.$ro​​otScope.Scope#$on 侦听器。