1049

AngularJS のホームページの「コンポーネントの作成」セクションに、次の例があります。

controller: function($scope, $element) {
  var panes = $scope.panes = [];
  $scope.select = function(pane) {
    angular.forEach(panes, function(pane) {
      pane.selected = false;
    });
    pane.selected = true;
  }
  this.addPane = function(pane) {
    if (panes.length == 0) $scope.select(pane);
    panes.push(pane);
  }
}

selectメソッドが に追加されていることに注意してください。$scopeただし、addPaneメソッドは に追加されていthisます。に変更すると$scope.addPane、コードが壊れます。

ドキュメントには、実際には違いがあると書かれていますが、違いについては言及されていません。

Angular の以前のバージョン (1.0 RC より前) ではthis、メソッドと同じ意味で使用でき$scopeましたが、現在はそうではありません。thisスコープで定義されたメソッドの内部で$scope交換可能 (angular をthisに設定$scope) ですが、それ以外の場合はコントローラー コンストラクター内ではできません。

AngularJS コントローラーでどのようthisに機能しますか?$scope

4

7 に答える 7

1014

「 AngularJSコントローラーではどのようthisに機能しますか?」$scope

短い答え

  • this
    • コントローラーコンストラクター関数が呼び出されると、thisはコントローラーになります。
    • $scopeオブジェクトに定義されたthis関数が呼び出されたとき、は「関数が呼び出されたときに有効だったスコープ」です。これは$scope、関数が定義されているものである場合もあれば、そうでない場合もあります。したがって、関数内で、同じthis$scopeない可能性があります。
  • $scope
    • すべてのコントローラーには、関連付けられた$scopeオブジェクトがあります。
    • コントローラー(コンストラクター)関数は、関連するモデルのプロパティと関数/動作を設定する役割を果たします$scope
    • $scopeこのオブジェクト(およびプロトタイプの継承が機能している場合は親スコープオブジェクト)で定義されたメソッドのみが、HTML/ビューからアクセスできます。たとえば、from ng-click、filtersなど。

長い答え

コントローラー関数はJavaScriptコンストラクター関数です。コンストラクター関数が実行されるとき(たとえば、ビューがロードされるとき)、this(つまり、「関数コンテキスト」)がコントローラーオブジェクトに設定されます。したがって、「タブ」コントローラーコンストラクター関数では、addPane関数が作成されると

this.addPane = function(pane) { ... }

$ scopeではなく、コントローラーオブジェクトに作成されます。ビューはaddPane関数を見ることができません-ビューは$scopeで定義された関数にのみアクセスできます。つまり、HTMLでは、これは機能しません。

<a ng-click="addPane(newPane)">won't work</a>

「tabs」コントローラーコンストラクター関数が実行されると、次のようになります。

タブ後コントローラーコンストラクター関数

黒い破線は、プロトタイプの継承を示します。分離スコープは、プロトタイプからスコープを継承します。(通常、HTMLでディレクティブが検出されたスコープからは継承されません。)

ここで、paneディレクティブのリンク関数は、tabsディレクティブと通信する必要があります(つまり、タブの分離$ scopeに何らかの影響を与える必要があることを意味します)。イベントを使用することもできますが、別のメカニズムは、ペインディレクティブrequireをタブコントローラーにすることです。require(タブ$ scopeへのペインディレクティブのメカニズムはないようです。)

だから、これは疑問を投げかけます:タブコントローラーにしかアクセスできない場合、タブ分離$ scopeにアクセスするにはどうすればよいですか(これは私たちが本当に望んでいることです)?

さて、赤い点線が答えです。addPane()関数の「スコープ」(ここではJavaScriptの関数スコープ/クロージャを参照しています)により、関数はタブの分離$scopeにアクセスできます。つまり、addPane()が定義されたときに作成されたクロージャのため、addPane()は上の図の「タブIsolateScope」にアクセスできます。(代わりに、タブ$ scopeオブジェクトでaddPane()を定義した場合、ペインディレクティブはこの関数にアクセスできないため、タブ$ scopeと通信する方法がありません。)

あなたの質問の他の部分に答えるにはhow does $scope work in controllers?::

$ scopeで定義された関数内で、this「関数が呼び出された場所/ときに有効な$scope」に設定されます。次のHTMLがあるとします。

<div ng-controller="ParentCtrl">
   <a ng-click="logThisAndScope()">log "this" and $scope</a> - parent scope
   <div ng-controller="ChildCtrl">
      <a ng-click="logThisAndScope()">log "this" and $scope</a> - child scope
   </div>
</div>

そしてParentCtrl(唯一の)持っている

$scope.logThisAndScope = function() {
    console.log(this, $scope)
}

最初のリンクをクリックすると、「関数が呼び出されたときに有効だったスコープ」がに関連付けられたスコープであるため、this$scopeは同じであることが示されます。ParentCtrl

2番目のリンクをクリックすると、「関数が呼び出されたときに有効だったスコープ」がに関連付けられたスコープであるため、同じでthis$scopeなく表示されます。したがって、ここでは、は'sに設定されます。メソッド内には、まだの$scopeがあります。ChildCtrlthisChildCtrl$scope$scopeParentCtrl

フィドル

$ scopeで定義された関数の内部では使用しないようにしていますthis。特に、ng-repeat、ng-include、ng-switch、およびディレクティブがすべて独自の子スコープを作成できることを考えると、影響を受ける$scopeが混乱するためです。

于 2013-01-05T04:48:53.450 に答える
56

これに「addPane」が割り当てられているのは、<pane>ディレクティブのためです。

このpaneディレクティブはrequire: '^tabs'、タブ コントローラー オブジェクトを親ディレクティブからリンク関数に配置します。

addPaneに割り当てられてthisいるため、paneリンク機能から参照できます。次に、paneリンク関数でaddPaneは、コントローラーの単なるプロパティでありtabs、それは単なる tabsControllerObject.addPane です。したがって、ペイン ディレクティブのリンク関数はタブ コントローラー オブジェクトにアクセスできるため、addPane メソッドにアクセスできます。

私の説明が十分に明確であることを願っています..説明するのはちょっと難しいです.

于 2012-07-23T15:20:37.993 に答える
28

2つの違いに関する非常に興味深い説明を読んだところです。モデルをコントローラーにアタッチし、コントローラーをエイリアスしてモデルをビューにバインドするという好みが高まっています。http://toddmotto.com/digging-into-angulars-controller-as-syntax/が記事です。

注:元のリンクはまだ存在しますが、書式設定が変更されて読みにくくなっています。オリジナルの方が見やすいです。

彼はそれについて言及していませんが、ディレクティブを定義するときに、複数のディレクティブ間で何かを共有する必要があり、サービスが必要ない場合 (サービスが面倒な正当なケースがあります)、データを親ディレクティブのコントローラーにアタッチします。

$scopeサービスは多くの便利なものを提供し、$watch最も明白ですが、データをビューにバインドする必要がある場合は、テンプレートでプレーンコントローラーと「コントローラーとして」を使用することは問題なく、間違いなく望ましいことです。

于 2014-08-28T21:25:47.997 に答える
20

次の投稿を読むことをお勧めします: AngularJS: "Controller as" or "$scope"?

「$scope」を介して変数を公開するために「Controller as」を使用する利点が非常によく説明されています。

変数ではなくメソッドについて具体的に質問されたことは知っていますが、1 つの手法に固執し、それと一貫性を保つ方がよいと思います。

したがって、私の意見では、投稿で説明されている変数の問題のため、「Controller as」手法を使用し、それをメソッドにも適用することをお勧めします。

于 2015-11-03T10:31:26.733 に答える
16

このコース ( https://www.codeschool.com/courses/shaping-up-with-angular-js ) では、"this" の使い方やその他の多くのことを説明しています。

「this」メソッドを介してコントローラーにメソッドを追加する場合は、コントローラーの名前「ドット」でプロパティまたはメソッドを使用してビューで呼び出す必要があります。

たとえば、ビューでコントローラーを使用すると、次のようなコードが表示される場合があります。

    <div data-ng-controller="YourController as aliasOfYourController">

       Your first pane is {{aliasOfYourController.panes[0]}}

    </div>
于 2014-09-24T07:29:37.670 に答える