ネストされたディレクティブ間の通信


61

ディレクティブ間で通信する方法はかなりあるようです。ネストされたディレクティブがあるとします。ここでは、内側のディレクティブが外側に何かを伝える必要があります(たとえば、ユーザーによって選択されます)。

<outer>
  <inner></inner>
  <inner></inner>
</outer>

これまでにこれを行うには5つの方法があります

require: 親ディレクティブ

innerディレクティブが必要になることがありouter、そのコントローラ上のいくつかのメソッドを公開することができディレクティブを、。だからinner定義では

require: '^outer',
link: function(scope, iElement, iAttrs, outerController) {
   // This can be passed to ng-click in the template
   $scope.chosen = function() {
     outerController.chosen(something);
   }
}

そして、outerディレクティブのコントローラーで:

controller: function($scope) {
   this.chosen = function(something) {
   }
}

$emit 出来事

innerディレクティブができる$emitイベント、outerディレクティブは経由して、に応答することができます$on。そのため、innerディレクティブのコントローラーで:

controller: function($scope) {
  $scope.chosen = function() {
    $scope.$emit('inner::chosen', something);
  }
}

そして、でouterディレクティブコントローラ:

controller: function($scope) {
  $scope.$on('inner::chosen, function(e, data) {
  }
}

経由で親スコープで式を実行する &

アイテムは親スコープ内の式にバインドし、適切な時点で実行できます。HTMLは次のようになります。

<outer>
  <inner inner-choose="functionOnOuter(item)"></inner>
  <inner inner-choose="functionOnOuter(item)"></inner>
</outer>

そのため、innerコントローラーには呼び出すことができる「innerChoose」関数があります

scope: {
  'innerChoose': '&'
},
controller: function() {
  $scope.click = function() {
    $scope.innerChoose({item:something});
  }
}

outerディレクティブのスコープで(この場合) 'functionOnOuter'関数を呼び出します:

controller: function($scope) {
  $scope.functionOnOuter = function(item) {
  }
}

非分離スコープでのスコープの継承

これらがネストされたコントローラーであることを考えると、スコープの継承が機能し、内部ディレクティブは、孤立したスコープを持たない限り、スコープチェーン内の任意の関数を呼び出すことができます)。中のSO innerディレクティブ:

// scope: anything but a hash {}
controller: function() {
  $scope.click = function() {
    $scope.functionOnOuter(something);
  }
}

そしてouterディレクティブでは:

controller: function($scope) {
  $scope.functionOnOuter = function(item) {
  }
}

内側と外側の両方に注入されたサービスにより

サービスは両方のディレクティブに挿入できるため、同じオブジェクトに直接アクセスしたり、関数を呼び出してサービスに通知したり、場合によってはpub / subシステムで通知されるように登録することもできます。これには、ディレクティブをネストする必要はありません。

質問:他のものに対するそれぞれの潜在的な欠点と利点は何ですか?


5
私は今までこの質問を見たことがないとは信じられません。あなたが提供したすべてのオプションに感謝します。まだ行っていない場合、この質問をstackoverflowに投稿することを考えましたか?私は、それがstackoverflowではるかに多くの牽引を得ると予想します。
マイクバーロウ-BarDev 14

回答:


7

私の好みは、&主にディレクティブのscope: {}定義をAPIとして見るため、ディレクティブスコープで属性を定義することです。スコープ属性の定義を見て、ディレクティブが適切に機能するために必要な情報を確認する方が、$emit'dイベント、継承されたスコープ関数、または注入されたコントローラー内で使用される関数のリンクおよびコントローラー関数を探すよりもはるかに簡単です。


1

私の意見:

サービスは、モジュール/ディレクティブ/コントローラー間で動作/データを共有する好ましい方法です。ディレクティブは、入れ子にすることも入れないこともできる孤立したものです。コントローラはできる限りビューモデルに固執する必要があります。理想的には、ビジネスロジックがそこに到達しないようにする必要があります。

そう:

親スコープ関数にアクセスしてそれらの配線を開始すると、それらのカップリングが強すぎて、アプリケーション全体が読みにくくなり、コンポーネントが再利用できなくなる可能性があります。サービスでその共有データまたは動作を分離すると、実行時に使用するサービスを決定する場合でも、異なるデータ/動作でディレクティブ全体を再利用できるという利点があります。これが依存性注入のすべてです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.