2015-10-24 7 views
10

隔離されたスコープ(再利用可能なアイテムかもしれない)で親と子の間で通信するための最良のGENERICアプローチは何かを理解しようとしています。

子ディレクティブは(両方がスコープを単離した)いくつかの方法で、親ディレクティブを更新する必要がある場合、 は私がコールバック関数を渡す 必要があります意味:

例:

.directive('filterReviewStepBox', function() { 
    return { 
     restrict: 'EA', 
     scop: { 
      //some data 
     }, 
     template: '<div>text<reusable-dir></reusable-dir call-back="foo"></div>', 
     link: function (scope, elem, attrs) { 
      scope.foo = function() { 
       console.log('bar'); 
      }; 
     } 
    }; 
}).directive('reusableDir', function() { 
    return { 
     restrict: 'EA', 
     scope: { 
      callBack: '=callBack' 
       //other data 
     }, 
     template: '<div>text<button type="button" ng-click="bar"></button></div>', 
     link: function (scope, elem, attrs) { 
      scope.bar = function() { 
       scope.callBack(); 
      } 
     } 
    }; 
}); 

または私は$を使用する必要があります発する():

例:

directive('filterReviewStepBox', function() { 
     return { 
      restrict: 'EA', 
      scope: { 
       // some data 
      }, 
      template: '<div>text<reusable-dir></reusable-dir></div>', 
      link: function (scope, elem, attrs) { 
       scope.$on('foo', function() { 
        console.log('bar'); 
       }); 
      } 
     }; 
    }).directive('reusableDir', function() { 
     return { 
      restrict: 'EA', 
      scope: { //some data 
      }, 
      template: '<div>text<button type="button" ng-click="bar"></button></div>', 
      link: function (scope, elem, attrs) { 
       scope.bar = function() { 
        scope.$emit('foo'); 
       }; 
      } 
     }; 
    }); 

私はまだわからない

がオンライン最善のアプローチを探してみましたが、イムはまだ

EDIT

を踏みつけているEMITが大規模に理解しやすいが、パフォーマンスとオーバーヘッドが心配だろうと感じますが、イム

は私が

必要

忘れてしまいました

オプション。 でも、これが最も正しい解決策であるかどうかはまだ分かりません。 これは私が子供や孫を再利用することを許可していないので、その種類の指示は単一目的の項目になります。

+0

あなたは別のディレクティブのコントローラにアクセスすることができます 'require'オプションがあります。これはあなたが望むことをすることができるはずです。 – ieaglle

+0

私はあなたが言っていることを見ている...それについて考えていない...しかし、私は子供が再利用可能にしたい場合はどうなりますか?あなたのアプローチは使用できません。 –

+0

私の編集 –

答えて

0

この目的のためには、「必須」属性を使用するのが最良です。 https://docs.angularjs.org/api/ng/service/ $

別のディレクティブを必要とし、リンク機能への第四 の引数としてそのコントローラーを注入をコンパイル:

指令への完全なガイドでは、この程度の属性を必要と教えてください。ザ・ディレクティブ(複数可)の文字列名(または文字列の 配列)を渡すために取る必要があります。

はちょうどそれが、いくつかの親ディレクティブを探して、そのコントローラーを取る必要がありますディレクティブを伝える必要。ディレクティブに^という接頭辞を付けて検索し、この要件がオプションであるかどうかをと伝えるように指示できますか?接頭辞。

私はあなたの例を変更したので、reusableDirはfilterReviewStepBoxコントローラを呼び出すことができますが、単独でも使用できます。

http://jsbin.com/gedaximeko/edit?html,js,console,output

angular.module('stackApp', []) 
.directive('filterReviewStepBox', function() { 
     return { 
      restrict: 'EA', 
      scope: { 
       // some data 
      }, 
      template: '<div>text<reusable-dir></reusable-dir></div>', 
      link: function (scope, elem, attrs) { 

      }, 
      controller : function() { 
       this.notify = function(value) { 
       console.log('Notified : ' + value); 
       };    
      }, 
      controllerAs: 'vm', 
      bindToController: true 
     }; 
    }).directive('reusableDir', function() { 
     return { 
      restrict: 'EA', 
      scope: { //some data 
      }, 
      require: '?^filterReviewStepBox', 
      template: '<div>text<button type="button" ng-click="bar()"></button></div>', 
      link: function (scope, elem, attrs, controller) { 
       scope.bar = function() { 
        if (controller) { 
        controller.notify('foo'); 
        } 
       }; 
      } 
     }; 
    }); 
+0

あなたのソリューションはコントローラオプションを利用していますが、これは私がこの質問をした理由である親コントローラを予測できない汎用ディレクティブについても私の問題を解決しません。ここで私は厳密なコントローラを定義していてもいなくても、複数のコントローラ間では動作しません。つまり、コントローラ1とコントローラ2で使用できないので、一般的に実装できるので、$ emitまたはコールバックを使用するのが好ましい。 –

+0

ディレクティブのようなものが誰を呼んでいるのかわからない場合、$ emitは本当により一般的です。私は私がtranscludeを利用しているのでコールバックを使用しません。したがって、私のreusableDirは親のテンプレートの中にはありません。しかし、それはあなたが「子どもや孫」を再利用することを許さないということはどういう意味ですか? –

+0

あなたが実際に親または祖父母コントローラを使用するように強制されているので、別のコントローラで機能とコールバックを使用したい場合、私はcan not ...個人的には、ベストプラクティス –

0

私はあなたにも、設計やメンテナンスの観点から考慮にさらにいくつかの要因を取る必要があり、それはパフォーマンスについてだけではないと思います。

  1. コールバックメソッド:これはおそらく最も効率的なオプションです。子ディレクティブはparentディレクティブのメソッドを1つ呼び出すだけで、オーバーヘッドは ではありません。 https://stackoverflow.com/a/27997722/2889528

  2. エミット(またはそのこと放送用):このメソッドは、階層にすべての$の範囲(S)アップ(EMIT)またはダウン(ブロードキャスト)にイベントを発行し、かなりの数のオプションがここで説明があります、 は比較的高価ですが、$ scopeが使用可能な場合は、 イベントを監視して処理する柔軟性が得られます。

  3. 注射可能共通サービス:このオプションは、$ scopeが使用できないメソッドを呼び出す場合に使用できます。しかし、それはサービスにしっかりと依存していました。これは、 パブサブデザインの詳細です。

1

個人的には、自分のカスタムイベントを生成しないようにしています。主に、不要なイベントの伝播やバブリング(しばしば不要なスコープダイジェストを引き起こす)を引き起こすことは信じられないほど簡単ですが、大きなアプリケーションでは管理が難しくなるシステマティックな「ノイズ」も原因です。

私自身の個人的な意見は別にして、あなたが探しているより将来的なアプローチであれば、コールバックアプローチははるかに安全です。ここでは、なぜだ...

  • Angular2は、子から親への通信に依存ディレクティブとコンポーネントからonChange属性を公開し、開発者を奨励しています。これらは、束縛された関数以上のものではなく、指定されたコンポーネントまたは指令のバインディングまたはスコープに応じて定義する必要があります。
  • 上記と同様に、Angular2は、バインディングの変更をサブスクライブするコントローラが定義できるngOnChangesメソッドを示しています。このメソッドが提供されている場合は、DOM操作が発生する前に(新しいバインド値で)呼び出されるため、現在のAngularJS $scope.$watch実装よりも、親の子とのより一般的な親通信の候補になります。

ただし、記載されていないものは、AngularJSとAngular2の両方でサービスを介した通信が推奨されることです。


関連する問題