の中に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
、コードが壊れます。
ドキュメントには実際に違いがあると書かれていますが、その違いが何であるかは書かれていません。
this
以前のバージョンの Angular (1.0 RC より前) では、 メソッドと を互換的に使用できました$scope
が、現在はそうではありません。 スコープで定義された メソッドと の内部ではthis
、 は$scope
互換可能です (Angularthis
は に設定します$scope
) が、コントローラー コンストラクター内ではそうではありません。
AngularJS コントローラーではthis
と はどのように機能しますか?$scope
ベストアンサー1
「AngularJS コントローラーでは
this
と はどのように機能しますか?」$scope
短い答え:
this
- コントローラーのコンストラクター関数が呼び出されると、
this
コントローラーになります。 - オブジェクトで定義された関数が
$scope
呼び出されると、this
は「関数が呼び出されたときに有効だったスコープ」になります。これは、$scope
関数が定義されている である可能性があります (またはそうでない可能性があります)。したがって、関数内では、this
と は同じではない$scope
可能性があります。
- コントローラーのコンストラクター関数が呼び出されると、
$scope
- すべてのコントローラーには関連付けられた
$scope
オブジェクトがあります。 - コントローラー (コンストラクター) 関数は、関連付けられているモデルのプロパティと関数/動作を設定する役割を担います
$scope
。 - この
$scope
オブジェクト (およびプロトタイプ継承が使用されている場合は親スコープ オブジェクト) で定義されたメソッドのみが HTML/ビューからアクセスできます。例:ng-click
、フィルターなど。
- すべてのコントローラーには関連付けられた
長い答え:
コントローラ関数はJavaScriptのコンストラクタ関数です。コンストラクタ関数が実行されると(例えば、ビューがロードされるとき)、this
(つまり「関数コンテキスト」)がコントローラオブジェクトに設定されます。したがって、「tabs」コントローラコンストラクタ関数では、addPane関数が作成されると
this.addPane = function(pane) { ... }
これは $scope ではなく、コントローラ オブジェクト上に作成されます。ビューは addPane 関数を参照できません。ビューは $scope で定義された関数にのみアクセスできます。言い換えると、HTML ではこれは機能しません。
<a ng-click="addPane(newPane)">won't work</a>
「tabs」コントローラーのコンストラクター関数が実行されると、次のようになります。
破線の黒い線はプロトタイプ継承を示しています。分離スコープはプロトタイプ継承を行います。範囲(HTML 内でディレクティブが検出された場所の有効なスコープからプロトタイプ的に継承されるわけではありません。)
ここで、ペイン ディレクティブのリンク関数は、タブ ディレクティブと通信しようとします (つまり、何らかの方法でタブ分離 $scope に影響を与える必要があります)。イベントを使用することもできますが、別のメカニズムとして、ペイン ディレクティブをrequire
タブ コントローラーにすることもできます (ペイン ディレクティブをタブ $scope に関連付けるメカニズムはないようですrequire
)。
そこで、次のような疑問が生じます。タブ コントローラーにしかアクセスできない場合、タブ分離 $scope (これが本当に必要なことです) にはどのようにアクセスすればよいのでしょうか。
答えは赤い点線です。addPane() 関数の「スコープ」(ここでは JavaScript の関数スコープ/クロージャを参照しています) は、関数にタブ分離 $scope へのアクセスを提供します。つまり、addPane() が定義されたときに作成されたクロージャにより、addPane() は上の図の「タブ IsolateScope」にアクセスできます。(代わりに tabs $scope オブジェクトで addPane() を定義した場合、ペイン ディレクティブはこの関数にアクセスできず、したがって tabs $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
。
this
2 番目のリンクをクリックすると、 とは同じではない$scope
ことがわかります。これは、「関数が呼び出されたときに有効だったスコープ」が に関連付けられたスコープであるためです。したがって、ここでは がの に設定されます。メソッド内では、は の $scope のままです。ChildCtrl
this
ChildCtrl
$scope
$scope
ParentCtrl
特に ng-repeat、ng-include、ng-switch、およびディレクティブはすべて独自の子スコープを作成できることを考慮すると、どの $scope が影響を受けるのかが混乱するため、$scope で定義されthis
た関数内では使用しないようにしています。