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
で定義されたメソッドの内部は交換可能です(角度セットthis
から$scope
)。ただし、それ以外はコントローラーコンストラクターの内部では交換できません。
AngularJSコントローラでthis
と$scope
はどのように機能しますか?
「
this
および$scope
は、AngularJSコントローラーでどのように機能しますか?」
短い答え:
this
this
がコントローラーになります。$scope
オブジェクトで定義された関数が呼び出されると、this
は「関数が呼び出されたときに有効なスコープ」になります。これは、関数が定義されている$scope
である場合とそうでない場合があります。そのため、関数内では、this
と$scope
は同じnotになる場合があります。$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>
「タブ」コントローラーコンストラクター関数が実行されると、次のようになります。
黒い破線はプロトタイプの継承を示します-分離スコープは Scope からプロトタイプ的に継承します。 (HTMLでディレクティブが検出された有効なスコープからプロトタイプ的に継承することはありません。)
現在、ペインディレクティブのリンク関数は、tabsディレクティブと通信する必要があります(つまり、何らかの方法でタブアイソレート$ 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
に関連付けられたスコープだからです。
2番目のリンクをクリックすると、this
と$scope
がnot同じであることがわかります。これは、「関数が呼び出されました "はChildCtrl
に関連付けられたスコープです。したがって、ここでは、this
はChildCtrl
の$scope
に設定されます。メソッド内では、$scope
は依然としてParentCtrl
の$ scopeです。
特に、ng-repeat、ng-include、ng-switch、およびディレクティブがすべて独自の子スコープを作成できることを考慮すると、どの$ scopeが影響を受けているかがわかりにくくなるため、$ scopeで定義された関数内でthis
を使用しないようにしています。
これに 'addPane'が割り当てられているのは、<pane>
ディレクティブが原因です。
pane
ディレクティブはrequire: '^tabs'
を実行します。これは、タブディレクティブオブジェクトを親ディレクティブからリンク関数に渡します。
addPane
はthis
に割り当てられているので、pane
リンク関数はそれを見ることができます。それでpane
リンク関数では、addPane
はtabs
コントローラーの単なるプロパティーであり、それはtabsControllerObject.addPaneです。そのため、paneディレクティブのリンク関数はtabsコントローラオブジェクトにアクセスできるため、addPaneメソッドにアクセスできます。
私の説明が十分明確であることを願っています。説明するのは難しいです。
この2つの違いについてのかなり興味深い説明と、モデルをコントローラにアタッチしたり、モデルをビューにバインドするためにコントローラをエイリアスにしたりする傾向が高まっています。 http://toddmotto.com/digging-into-angulars-controller-as-syntax/ が記事です。彼はそれについては触れていませんが、ディレクティブを定義するときに、複数のディレクティブ間で何かを共有する必要があり、サービスが欲しくない場合(サービスが面倒な合法的な場合があります)、データを親ディレクティブのコントローラーに添付します。 $ scopeサービスはたくさんの便利なものを提供します。$ watchが最も明白ですが、データをビューにバインドする必要がある場合は、プレーンコントローラとテンプレートの 'controller as'を使用するのが賢く、間違いなく好ましいです。
次の記事を読むことをお勧めします: AngularJS: "Controller as"または "$ scope"?
これは、 "$ scope"を超えて変数を公開するために "Controller as"を使用することの利点を非常によく説明しています。
私はあなたが変数ではなくメソッドについて具体的に尋ねたことを知っています、しかし私はそれが一つのテクニックに固執してそれと一致しているほうが良いと思います。
それで、私の意見では、この記事で議論した変数の問題のために、単に "Controller as"テクニックを使い、それをメソッドにも適用するのが良いでしょう。
このコース( https://www.codeschool.com/courses/shaping-up-with-angular-js )では、「これ」や他の多くのものの使い方を説明しています。
"this"メソッドを使ってコントローラにメソッドを追加した場合は、プロパティまたはメソッドの "dot"というコントローラ名でそれをビュー内で呼び出す必要があります。
たとえば、ビューでコントローラを使用すると、次のようなコードになります。
<div data-ng-controller="YourController as aliasOfYourController">
Your first pane is {{aliasOfYourController.panes[0]}}
</div>
以前のバージョンのAngular(1.0 RC以前)では、これを$ scopeメソッドと互換的に使用できましたが、これはもはや当てはまりません。スコープthisと$ scopeで定義されたメソッドの中では互換性があります(angleはこれを$ scopeに設定します)が、そうでなければあなたのコントローラコンストラクタの中ではそうではありません。
この振る舞いを取り戻すために(誰がそれがなぜ変更されたのか知っていますか?)あなたは追加することができます:
return angular.extend($scope, this);
あなたのコントローラ関数の最後に($ scopeがこのコントローラ関数に挿入されていれば).
これは、require: '^myParentDirective'
を使って子に取得できるコントローラオブジェクトを介して親スコープにアクセスできるという素晴らしい効果があります。
$ scopeにはコントローラー「this」とは異なる「this」があります。したがって、console.log(this)をコントローラー内に配置すると、オブジェクト(controller)が提供され、this.addPane()がコントローラーオブジェクトにaddPaneメソッドを追加します。ただし、$ scopeのスコープは異なり、そのスコープ内のすべてのメソッドは$ scope.methodName()にアクセスする必要があります。 this.methodName()
コントローラー内部では、コントローラーオブジェクト内にmethosを追加することを意味します。$scope.functionName()
はHTMLおよび内部にあります
$scope.functionName(){
this.name="Name";
//or
$scope.myname="myname"//are same}
このコードをエディターに貼り付けて、コンソールを開いて確認してください...
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=Edge">
<title>this $sope vs controller</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.7/angular.min.js"></script>
<script>
var app=angular.module("myApp",[]);
app.controller("ctrlExample",function($scope){
console.log("ctrl 'this'",this);
//this(object) of controller different then $scope
$scope.firstName="Andy";
$scope.lastName="Bot";
this.nickName="ABot";
this.controllerMethod=function(){
console.log("controllerMethod ",this);
}
$scope.show=function(){
console.log("$scope 'this",this);
//this of $scope
$scope.message="Welcome User";
}
});
</script>
</head>
<body ng-app="myApp" >
<div ng-controller="ctrlExample">
Comming From $SCOPE :{{firstName}}
<br><br>
Comming from $SCOPE:{{lastName}}
<br><br>
Should Come From Controller:{{nickName}}
<p>
Blank nickName is because nickName is attached to
'this' of controller.
</p>
<br><br>
<button ng-click="controllerMethod()">Controller Method</button>
<br><br>
<button ng-click="show()">Show</button>
<p>{{message}}</p>
</div>
</body>
</html>