【问题标题】:Accessing inherited scope with Controller As approach使用 Controller As 方法访问继承范围
【发布时间】:2014-12-26 04:00:54
【问题描述】:

使用定义控制器的原始方式,访问父级范围相当简单,因为子级范围原型继承自其父级。

app.controller("parentCtrl", function($scope){
   $scope.name = "Parent";
})
.controller("childCtrl", function($scope){
   $scope.childName = "child of " + $scope.name;
});

<div ng-controller="parentCtrl">
   {{name}}
   <div ng-controller="childCtrl">
      {{childName}}
   </div>
</div>

Controller-As 方法 似乎是 recommended 声明控制器的方式。但是对于 Controller-As,上述方法不再有效。

当然,我可以在视图中使用pc.name 访问父作用域:

<div ng-controller="parentCtrl as pc">
   {{pc.name}}
   <div ng-controller="childCtrl as cc">
      {{cc.childName}}
   </div>
</div>

我对此确实有一些问题(可能是意大利面条代码),但这个问题是关于从子控制器访问父范围的。

我能看到这个工作的唯一方法是:

app.controller("parentCtrl", function(){
   this.name = "parent";
})
.controller("childCtrl", function($scope){
   $scope.pc.name = "child of " + $scope.name;
   // or
   $scope.$parent.pc.name = "child of " + $scope.name;

   // there's no $scope.name
   // and no $scope.$parent.name
});

所以现在,子控制器需要知道“pc”——除了,这应该(在我看来)仅限于视图。我认为子控制器不应该知道视图决定声明 ng-controller="parentCtrl as pc" 的事实。

问:那么正确的方法是什么?

编辑:

澄清:我不打算继承父控制器。我正在寻找继承/更改共享范围。所以,如果我要修改第一个例子,我应该能够做到以下几点:

app.controller("parentCtrl", function($scope){
   $scope.someObj = {prop: "not set"};
})
.controller("childCtrl", function($scope){
   $scope.someObj.prop = "changed";
});

【问题讨论】:

  • Angular 的“控制器”实际上更像是“视图助手”或“视图模型”。建议使用controllerAs 的样式指南积极鼓励您直接使用pc 或掩盖这种情况。我想你可以在parentCtrlchildCtrl 之间建立一个继承链,例如childCtrl.prototype = Object.create(parentCtrl.prototype) 然后在你的 childCtrl 构造函数中,this.name 在你隐藏它之前会引用父母的名字。

标签: angularjs angularjs-scope angularjs-controller


【解决方案1】:

经过研究,我得出以下认识:

Controller-As 方法不能替代使用$scope。两者都有自己的位置,可以/应该明智地一起使用。

  1. $scope 完全符合其名称的含义:即它在 $scope 上定义 ViewModel 属性。这最适合与嵌套控制器共享范围,这些控制器可以使用$scope 来驱动自己的逻辑或更改它。
  2. Controler-As 将整个控制器对象定义为具有命名范围的 ViewModel(通过控制器的别名)。如果 View 决定是否要引用特定的控制器 ViewModel,这仅在 View(而不是其他控制器)中最有效。

这是一个例子:

var app = angular.module('myApp', []);

// Then the controllers could choose whether they want to modify the inherited scope or not:
app.controller("ParentCtrl", function($scope) {
    this.prop1 = {
      v: "prop1 from ParentCtrl"
    };
    $scope.prop1 = {
      v: "defined on the scope by ParentCtrl"
    };
  })
  .controller("Child1Ctrl", function($scope) {})
  .controller("Child2Ctrl", function($scope) {
    // here, I don't know about the "pc" alias
    this.myProp = $scope.prop1.v + ", and changed by Child2Ctrl";
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.min.js"></script>

<body ng-app="myApp">
  <div ng-controller="ParentCtrl as pc">
     <div ng-controller="Child1Ctrl">
        <div>I know about the "pc" alias: {{pc.prop1.v}}</div>
     </div>
     <div ng-controller="Child2Ctrl as ch2">
       <div>I only care about my own ViewModel: {{ch2.myProp}}</div>
    </div>
  </div>

【讨论】:

  • 所以你基本上是说使用“控制器作为”时访问孩子内部的父母范围是不可行的?我认为 OP ($scope.$parent.pc.name) 列出的方法不可行。
【解决方案2】:

你应该这样做:

html

<div ng-controller="ChildController as child">
    <button type="button" ng-click="child.sayMe()">Say me!</button>
</div>

js

var app = angular.module('myApp', [])
app.controller('BaseController',function() {
    this.me = 'Base';
    this.sayMe= function() {
        alert(this.me);
    }
});
app.controller('ChildController', function($scope, $controller) {
    var controller = $controller('BaseController as base', {$scope: $scope});
    angular.extend(this, controller);
    this.me = 'Child';
});

看看https://docs.angularjs.org/guide/controller

【讨论】:

  • 我的意图(对不起,如果没有正确传达)不是继承基本控制器,而是继承范围。我不想知道哪个父控制器在那里 - 我只想依赖范围(根据我的第一个示例)。
  • 好的,所以我知道的唯一方法是使用 $parent.$scope 或 $rootScope
  • @Whisher:这真的很有帮助。关于这一点的一个问题。将'BaseController as base'放在这里有什么需要?我可以简单地做'BaseController',因为无论如何,目的是继承属性/方法。如果我错了,请纠正我
  • @jitoppy 如果你不使用'controller as'语法,你可以毫无问题地使用'BaseController'
【解决方案3】:

对于希望以编程方式简单地访问父作用域的任何人,请使用$scope 服务,找到父作用域,然后访问用于父作用域的controllerAs 的名称,例如:

$scope.$parent.someName.doSomething();

【讨论】:

    猜你喜欢
    • 2016-01-24
    • 1970-01-01
    • 1970-01-01
    • 2015-07-19
    • 2013-02-13
    • 1970-01-01
    • 2014-12-06
    • 1970-01-01
    • 2010-10-01
    相关资源
    最近更新 更多