web-dev-qa-db-ja.com

Controller Asアプローチによる継承スコープへのアクセス

コントローラを定義する元の方法では、親のスコープへのアクセスはかなり簡単でした。子のスコープは典型的には親から継承するからです。

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アプローチは、コントローラーを宣言する 推奨 方法のようです。しかし、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"を宣言することを決定したという事実について、子コントローラーが知っているべきではないと思います。

Q:では、正しいアプローチは何ですか?

編集:

明確化:私は親コントローラーを継承するつもりはありません。共有スコープを継承/変更しようとしています。したがって、最初の例を修正する場合、次のことができるはずです。

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

調査した後、次のことに気付きました。

Controller-Asアプローチは、$scopeの使用に代わるものではありません。どちらにもそれぞれの場所があり、賢明に一緒に使用できる/すべきです。

  1. $scopeは、名前が示すとおりのことを行います。つまり、$scopeでViewModelプロパティを定義します。これは、$scopeを使用して独自のロジックを駆動または変更できるネストされたコントローラーとスコープを共有するのに最適です。
  2. Controler-Asは、コントローラーオブジェクト全体を(コントローラーのエイリアスを介して)名前付きスコープを持つViewModelとして定義します。これは、Viewが特定のコントローラーViewModelを参照するかどうかをViewが決定した場合にのみ、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>
62
New Dev

あなたは次のようにする必要があります:

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 をご覧ください

7
Whisher

プログラムで親スコープに単純にアクセスする場合は、_$scope_サービスを使用して親スコープを見つけ、親スコープのcontrollerAsに使用される名前にアクセスします。例:

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

1
Adam Reis