1096

このトピックに関するAngularJSのドキュメントを注意深く読んだ後、ディレクティブをいじりました。これがフィドルです。

そして、ここにいくつかの関連するスニペットがあります:

  • HTMLから:

    <pane bi-title="title" title="{{title}}">{{text}}</pane>
    
  • ペインディレクティブから:

    scope: { biTitle: '=', title: '@', bar: '=' },
    

私が得られないことがいくつかあります:

  • "{{title}}"一緒に使用する必要があるのはなぜですか?'@'"title"'='
  • 要素を属性で装飾せずに、親スコープに直接アクセスすることもできますか?
  • ドキュメントには、「分離されたスコープから式を介して親スコープにデータを渡すことが望ましい場合が多い」と記載されていますが、双方向バインディングでも問題なく機能するようです。なぜ表現ルートが良いのでしょうか?

式の解決策を示す別のフィドルも見つけました:http://jsfiddle.net/maxisam/QrCXh/

4

18 に答える 18

1167

「{{title}}」を「 @」で使用し、「title」を「= 」で使用する必要があるのはなぜですか?

@は、ローカル/ディレクティブスコーププロパティをDOM属性の評価値にバインドします。title=title1またはを使用する場合title="title1"、DOM属性「title」の値は単に文字列title1です。を使用する場合title="{{title}}"、DOM属性 "title"の値はの補間値で{{title}}あるため、文字列は現在設定されている親スコーププロパティ"title"になります。属性値は常に文字列であるため、@を使用すると、ディレクティブのスコープ内のこのプロパティの文字列値になります。

=ローカル/ディレクティブスコーププロパティを親スコーププロパティにバインドします。したがって、=を使用すると、親モデル/スコープのプロパティ名をDOM属性の値として使用します。={{}}でsを使用することはできません。

@を使用すると、次のようなことができますtitle="{{title}} and then some"-{{title}}が補間され、文字列「andthemsome」が連結されます。最後の連結文字列は、ローカル/ディレクティブスコーププロパティが取得するものです。(これは=で行うことはできず、 @のみで行うことができます。)

@を使用attr.$observe('title', function(value) { ... })すると、link(ing)関数で値を使用する必要がある場合に使用する必要があります。たとえば、if(scope.title == "...")期待どおりに機能しません。これは、この属性に非同期でしかアクセスできないことを意味することに注意してください。テンプレートの値のみを使用している場合は、$ observe()を使用する必要はありません。例:template: '<div>{{title}}</div>'

=を使用すると、$observeを使用する必要はありません。

要素を属性で装飾せずに、親スコープに直接アクセスすることもできますか?

はい。ただし、分離スコープを使用しない場合に限ります。ディレクティブからこの行を削除します

scope: { ... }

そうすれば、ディレクティブは新しいスコープを作成しません。親スコープを使用します。その後、すべての親スコープのプロパティに直接アクセスできます。

ドキュメントには、「分離されたスコープから式を介して親スコープにデータを渡すことが望ましい場合が多い」と記載されていますが、双方向バインディングでも問題なく機能するようです。なぜ表現ルートが良いのでしょうか?

はい、双方向バインディングにより、ローカル/ディレクティブスコープと親スコープがデータを共有できます。「式バインディング」を使用すると、ディレクティブでDOM属性で定義された式(または関数)を呼び出すことができます。また、式または関数に引数としてデータを渡すこともできます。したがって、親とデータを共有する必要がない場合(親スコープで定義された関数を呼び出すだけの場合)は、構文を使用できます。

も参照してください

于 2012-12-28T01:15:27.413 に答える
550

ここには素晴らしい答えがたくさんありますが、、、、およびバインディングの違いについて@、私にとって有用であることがわかったという私の見解を示したいと思います。=&

3つのバインディングはすべて、要素の属性を介して、親スコープからディレクティブの分離スコープにデータを渡す方法です。

  1. @バインディングは、文字列を渡すためのものです。これらの文字列{{}}は、補間された値の式をサポートします。例えば: 。補間された式は、ディレクティブの親スコープに対して評価されます。

  2. =バインディングは双方向モデルバインディング用です。親スコープのモデルは、ディレクティブの分離スコープのモデルにリンクされています。一方のモデルへの変更はもう一方のモデルに影響し、その逆も同様です。

  3. バインディングは、ディレクティブ内で呼び出すことができるように、ディレクティブのスコープにメソッドを渡すためのものです。このメソッドは、ディレクティブの親スコープに事前にバインドされており、引数をサポートしています。たとえば、メソッドが親スコープのhello(name)である場合、ディレクティブ内からメソッドを実行するには、$ scope.hello({name:'world'})を呼び出す必要があります。

短い説明でスコープバインディングを参照すると、これらの違いを覚えやすくなります。

  • @ 属性文字列バインディング
  • = 双方向モデルバインディング
  • & コールバックメソッドバインディング

シンボルはまた、スコープ変数がディレクティブの実装内で何を表すかを明確にします。

  • @ ストリング
  • = モデル
  • & 方法

有用性の順に(とにかく私にとって):

  1. =
  2. @
于 2015-02-03T23:30:29.020 に答える
67

=双方向バインディングを意味するため、親スコープへの変数への参照。つまり、ディレクティブで変数を変更すると、親スコープでも変更されます。

@変数がディレクティブにコピー(複製)されることを意味します。

私の知る限り、<pane bi-title="{{title}}" title="{{title}}">{{text}}</pane>うまくいくはずです。bi-title親スコープ変数値を受け取ります。これは、ディレクティブで変更できます。

親スコープ内の複数の変数を変更する必要がある場合は、ディレクティブ内から親スコープで関数を実行できます(またはサービスを介してデータを渡します)。

于 2012-12-27T06:20:30.460 に答える
39

これが実際の例でどのように機能するかをもっと知りたい場合。http://jsfiddle.net/juanmendez/k6chmnch/

var app = angular.module('app', []);
app.controller("myController", function ($scope) {
    $scope.title = "binding";
});
app.directive("jmFind", function () {
    return {
        replace: true,
        restrict: 'C',
        transclude: true,
        scope: {
            title1: "=",
            title2: "@"
        },
        template: "<div><p>{{title1}} {{title2}}</p></div>"
    };
});
于 2014-11-21T23:19:34.233 に答える
39

@ 文字列として取得

  • これにより、バインディングは作成されません。渡した単語を文字列として取得しているだけです

= 2ウェイバインディング

  • コントローラから行われた変更は、ディレクティブが保持する参照に反映され、その逆も同様です。

&スコープはで渡されたオブジェクトを返す関数を取得するため、これは少し異なる動作をします。私はこれがそれを機能させるために必要だったと思います。フィドルはこれを明確にする必要があります。

  • このゲッター関数を呼び出した後、結果のオブジェクトは次のように動作します。
    • 関数が渡された場合:呼び出されたときに、関数は親(コントローラー)クロージャーで実行されます
    • 非関数が渡された場合:バインディングのないオブジェクトのローカルコピーを取得するだけです


このフィドルは、それらがどのように機能するかを示す必要があります。名前に含まれるスコープ関数に特に注意して、get...私が何を意味するのかをよりよく理解してください。&

于 2015-08-26T03:40:26.873 に答える
38

ディレクティブにスコープを追加する方法は3つあります。

  1. 親スコープ:これはデフォルトのスコープ継承です。

ディレクティブとその親(それが含まれるコントローラー/ディレクティブ)スコープは同じです。したがって、ディレクティブ内のスコープ変数に加えられた変更は、親コントローラーにも反映されます。これはデフォルトであるため、指定する必要はありません。

  1. 子スコープ:ディレクティブは、ディレクティブのスコープ変数をtrueとして指定した場合に、親スコープから継承する子スコープを作成します。

ここで、ディレクティブ内のスコープ変数を変更すると、親スコープには反映されませんが、親のスコープ変数を実際に変更したため、親スコープに反映されるスコープ変数のプロパティを変更すると、 。

例、

app.directive("myDirective", function(){

    return {
        restrict: "EA",
        scope: true,
        link: function(element, scope, attrs){
            scope.somvar = "new value"; //doesnot reflect in the parent scope
            scope.someObj.someProp = "new value"; //reflects as someObj is of parent, we modified that but did not override.
        }
    };
});
  1. 分離スコープ:これは、コントローラースコープから継承しないスコープを作成する場合に使用されます。

これは、プラグインを作成しているときに発生します。これにより、ディレクティブは任意のHTMLに配置でき、親スコープの影響を受けないため、汎用になります。

これで、親スコープとの対話が必要ない場合は、スコープを空のオブジェクトとして指定できます。お気に入り、

scope: {} //this does not interact with the parent scope in any way

親スコープとの相互作用が必要なため、ほとんどの場合これは当てはまりません。したがって、値/変更の一部を通過させる必要があります。このため、以下を使用します。

1. "@"   (  Text binding / one-way binding )
2. "="   ( Direct model binding / two-way binding )
3. "&"   ( Behaviour binding / Method binding  )

@は、コントローラースコープからの変更がディレクティブスコープに反映されることを意味しますが、ディレクティブスコープの値を変更しても、コントローラースコープ変数は影響を受けません。

@は、マップされた属性が式であることを常に期待します。これは非常に重要です; 「@」プレフィックスを機能させるには、属性値を{{}}内にラップする必要があるためです。

=は双方向であるため、ディレクティブスコープで変数を変更すると、コントローラースコープ変数も影響を受けます

は、コントローラースコープメソッドをバインドするために使用されます。これにより、必要に応じて、ディレクティブから呼び出すことができます。

ここでの利点は、変数の名前がコントローラースコープとディレクティブスコープで同じである必要がないことです。

たとえば、ディレクティブスコープには、コントローラースコープの変数「contVar」と同期する変数「dirVar」があります。これにより、1つのコントローラーが変数v1と同期できる一方で、同じディレクティブを使用する別のコントローラーがdirVarに変数v2と同期するように要求できるため、ディレクティブに多くの機能と一般化が与えられます。

以下は使用例です。

ディレクティブとコントローラーは次のとおりです。

 var app = angular.module("app", []);
 app.controller("MainCtrl", function( $scope ){
    $scope.name = "Harry";
    $scope.color = "#333333";
    $scope.reverseName = function(){
     $scope.name = $scope.name.split("").reverse().join("");
    };
    $scope.randomColor = function(){
        $scope.color = '#'+Math.floor(Math.random()*16777215).toString(16);
    };
});
app.directive("myDirective", function(){
    return {
        restrict: "EA",
        scope: {
            name: "@",
            color: "=",
            reverse: "&"
        },
        link: function(element, scope, attrs){
           //do something like
           $scope.reverse(); 
          //calling the controllers function
        }
    };
});

そしてhtml(@と=の違いに注意してください):

<div my-directive
  class="directive"
  name="{{name}}"
  reverse="reverseName()"
  color="color" >
</div>

これはそれをうまく説明しているブログへのリンクです。

于 2015-04-26T16:34:27.507 に答える
20

簡単に使用できます:-

  1. @:-一方向のデータバインディングの文字列値。一方向のデータバインディングでは、スコープ値をディレクティブにのみ渡すことができます

  2. =:-双方向データバインディングのオブジェクト値。双方向のデータバインディングでは、ディレクティブとhtmlのスコープ値を変更できます。

  3. :-メソッドと関数用。

編集

Angularバージョン1.5以降コンポーネント定義には、4つ の異なるタイプのバインディングがあります。

  1. = 双方向のデータバインディング:-値を変更すると、自動的に更新されます
  2. < 一方向バインディング:-親スコープからパラメーターを読み取り、更新したくない場合。

  3. @これは文字列パラメータ用です

  4. &これは、コンポーネントが親スコープに何かを出力する必要がある場合のコールバック用です

于 2016-08-29T10:44:27.550 に答える
14

それらの違いを示すAngularコードを含む小さなHTMLファイルを作成しました。

<!DOCTYPE html>
<html>
  <head>
    <title>Angular</title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
  </head>
  <body ng-app="myApp">
    <div ng-controller="myCtrl as VM">
      <a my-dir
        attr1="VM.sayHi('Juan')" <!-- scope: "=" -->
        attr2="VM.sayHi('Juan')" <!-- scope: "@" -->
        attr3="VM.sayHi('Juan')" <!-- scope: "&" -->
      ></a>
    </div>
    <script>
    angular.module("myApp", [])
    .controller("myCtrl", [function(){
      var vm = this;
      vm.sayHi = function(name){
        return ("Hey there, " + name);
      }
    }])
    .directive("myDir", [function(){
      return {
        scope: {
          attr1: "=",
          attr2: "@",
          attr3: "&"
        },
        link: function(scope){
          console.log(scope.attr1);   // =, logs "Hey there, Juan"
          console.log(scope.attr2);   // @, logs "VM.sayHi('Juan')"
          console.log(scope.attr3);   // &, logs "function (a){return h(c,a)}"
          console.log(scope.attr3()); // &, logs "Hey there, Juan"
        }
      }
    }]);
    </script>
  </body>
</html>
于 2015-12-17T14:26:57.937 に答える
9

この質問はすでに打ちのめされていますが、他の誰かがAngularJSスコープである恐ろしい混乱に苦しんでいる場合に備えて、とにかくこれを共有します。これは、、、、およびをカバー=します。完全な書き込みはここで見つけることができます。 <@&::


=双方向バインディングを確立します。親のプロパティを変更すると、子も変更されます。その逆も同様です。


<親から子への一方向のバインディングを確立します。親のプロパティを変更すると子も変更されますが、子のプロパティを変更しても親のプロパティには影響しません。


@タグ属性の文字列値を子プロパティに割り当てます。属性にが含まれている場合、式が別の文字列に評価されるたびに子プロパティが更新されます。例えば:

<child-component description="The movie title is {{$ctrl.movie.title}}" />
bindings: {
    description: '@', 
}

ここでdescription、子スコープのプロパティは式の現在の値になります"The movie title is {{$ctrl.movie.title}}"。ここmovieで、は親スコープのオブジェクトです。


&少し注意が必要です。実際、これを使用する理由はないようです。これにより、親スコープの式を評価し、パラメーターを子スコープの変数に置き換えることができます。例(plunk):

<child-component 
  foo = "myVar + $ctrl.parentVar + myOtherVar"
</child-component>
angular.module('heroApp').component('childComponent', {
  template: "<div>{{  $ctrl.parentFoo({myVar:5, myOtherVar:'xyz'})  }}</div>",
  bindings: {
    parentFoo: '&foo'
  }
});

が与えられるparentVar=10と、式parentFoo({myVar:5, myOtherVar:'xyz'})はに評価され5 + 10 + 'xyz'、コンポーネントは次のようにレンダリングされます。

<div>15xyz</div>

この複雑な機能をいつ使用したいと思いますか?&親スコープのコールバック関数を子スコープに渡すためによく使用されます。ただし、実際には、「<」を使用して関数を渡すことで同じ効果を得ることができます。これは、より簡単で、パラメーター()を渡すための厄介な中括弧構文を回避します{myVar:5, myOtherVar:'xyz'}。検討:

を使用したコールバック&

<child-component parent-foo="$ctrl.foo(bar)"/>
angular.module('heroApp').component('childComponent', {
  template: '<button ng-click="$ctrl.parentFoo({bar:'xyz'})">Call foo in parent</button>',
  bindings: {
    parentFoo: '&'
  }
});

を使用したコールバック<

<child-component parent-foo="$ctrl.foo"/>
angular.module('heroApp').component('childComponent', {
  template: '<button ng-click="$ctrl.parentFoo('xyz')">Call foo in parent</button>',
  bindings: {
    parentFoo: '<'
  }
});

オブジェクト(および配列)は、コピーではなく、子スコープへの参照によって渡されることに注意してください。これが意味するのは、それが一方向のバインディングであっても、親スコープと子スコープの両方で同じオブジェクトを操作しているということです。


動作中のさまざまなプレフィックスを確認するには、このプランクを開きます。

を使用したワンタイムバインディング(初期化)::

[公式ドキュメント]
AngularJSの新しいバージョンでは、子スコープのプロパティが1回だけ更新される1回限りのバインディングを持つオプションが導入されています。これにより、親プロパティを監視する必要がなくなるため、パフォーマンスが向上します。構文は上記とは異なります。ワンタイムバインディングを宣言するには、コンポーネントタグ::の式の前に次のように追加します。

<child-component 
  tagline = "::$ctrl.tagline">
</child-component>

taglineこれにより、一方向または双方向のバインディングを確立せずに、の値が子スコープに伝播されます。taglineが最初undefinedに親スコープにある場合、angularは変更されるまでそれを監視し、子スコープの対応するプロパティを1回更新します。

概要

次の表は、プロパティがオブジェクト、配列、文​​字列などであるかどうかに応じてプレフィックスがどのように機能するかを示しています。

さまざまな分離スコープバインディングのしくみ

于 2019-02-13T14:08:17.957 に答える
6

=ウェイは双方向バインディングであり、ディレクティブ内でライブ変更を行うことができます。誰かがその変数をディレクティブから変更すると、その変更されたデータがディレクティブ内にありますが、@ wayは双方向バインディングではありません。テキストのように機能します。一度バインドすると、その値だけが得られます。

より明確に理解するために、次のすばらしい記事を使用できます。

AngularJSディレクティブスコープ'@'および'='

于 2016-05-10T23:03:06.397 に答える
4

@ローカルスコーププロパティは、ディレクティブの外部で定義された文字列値にアクセスするために使用されます。

=外部スコープとディレクティブの分離スコープの間に双方向バインディングを作成する必要がある場合は、=文字を使用できます。

ローカルスコーププロパティを使用すると、ディレクティブのコンシューマーは、ディレクティブが呼び出すことができる関数を渡すことができます。

例を挙げて明確に理解できる以下のリンクを確認してください。とても便利だと思ったので、共有することを考えました。

http://weblogs.asp.net/dwahlin/creating-custom-angularjs-directives-part-2-isolate-scope

于 2016-02-05T13:12:00.427 に答える
3

例のようにスコープがローカルの場合でも、プロパティを介して親スコープにアクセスできます$parenttitle以下のコードで、親スコープで定義されていると仮定します。次に、次のようにタイトルにアクセスできます$parent.title

link : function(scope) { console.log(scope.$parent.title) },
template : "the parent has the title {{$parent.title}}"

ただし、ほとんどの場合、属性を使用すると同じ効果が得られます。

「分離されたスコープから式を介して親スコープにデータを渡すために」使用される「&」表記が有用である(そして双方向のデータバインディングは使用できなかった)例は、ディレクティブにありました。 ng-repeat内に特別なデータ構造をレンダリングするため。

<render data = "record" deleteFunction = "dataList.splice($index,1)" ng-repeat = "record in dataList" > </render>

レンダリングの一部は削除ボタンでした。ここでは、&を介して外部スコープから削除関数をアタッチすると便利でした。レンダリングディレクティブの内部は次のようになります

scope : { data = "=", deleteFunction = "&"},
template : "... <button ng-click = "deleteFunction()"></button>"

双方向データバインディング、つまりdata = "="、削除機能がすべての$digestサイクルで実行されるため使用できません。これは、レコードがすぐに削除され、レンダリングされないため、適切ではありません。

于 2014-07-11T08:32:25.483 に答える
3

私はすべての可能なオプションをフィドルに実装しました。

それはすべてのオプションを扱います:

scope:{
    name:'&'
},

scope:{
    name:'='
},

scope:{
    name:'@'
},

scope:{

},

scope:true,

https://jsfiddle.net/rishulmatta/v7xf2ujm

于 2015-12-20T06:15:56.773 に答える
3

それらの主な違いは

@ Attribute string binding
= Two-way model binding
& Callback method binding
于 2018-05-31T09:51:56.857 に答える
1

@そして=他の答えを見てください。

TL;DRに関する1つの落とし穴; 親から式(他の回答の例のように機能するだけでなく)を取得し、式を呼び出すディレクティブの関数として設定します。また、この関数には、オブジェクトを変数に渡すことにより、式の 任意の変数(関数名も含む)を置き換える機能があります。&

&

Explainedは式の参照です。つまり 、ディレクティブで次の
&ようなものを渡すと 、これは次のような式を呼び出す関数になります。 したがって、ディレクティブのhtmlでは式が呼び出されます。ディレクティブのjsでは、式も呼び出します。 式は、親の$scope.xと$scope.yを使用して呼び出されます。 パラメータを上書きすることができます! たとえば、呼び出しによってそれらを設定した場合 、式はパラメーターと親のパラメーターを使用して呼び出されます。 両方をオーバーライドできます。 今、あなたは知っています、なぜうまくいくのですか。 親の式を呼び出すだけなので(例:<myDirective expr="x==y"></myDirective>
expr
function expr(){return x == y}
<button ng-click="expr()"></button>$scope.expr()


<button ng-click="expr({x:5})"></button>
xy

<button ng-click="functionFromParent({x:5})"></button>
<myDirective functionFromParent="function1(x)"></myDirective>)そして可能な値を指定されたパラメータ(この場合は)に置き換えますx
それは次のようになります:
<myDirective functionFromParent="function1(x) + 5"></myDirective>
または
<myDirective functionFromParent="function1(x) + z"></myDirective>
子の呼び出しがある場合:
<button ng-click="functionFromParent({x:5, z: 4})"></button>
または関数置換を使用する場合でも:
<button ng-click="functionFromParent({function1: myfn, x:5, z: 4})"></button>

それは単なる式であり、それが関数であるか、多くの関数であるか、または単なる比較であるかは関係ありません。また、この式の任意の変数を置き換えることができます。

例:
ディレクティブテンプレートと呼び出されたコード:
親が定義した$ scope.x、$ scope.y:
親テンプレート:<myDirective expr="x==y"></myDirective>
<button ng-click="expr()"></button>呼び出し$scope.x==$scope.y
<button ng-click="expr({x: 5})"></button>呼び出し5 == $scope.y
<button ng-click="expr({x:5, y:6})"></button>呼び出し5 == 6

親が$scope.function1、$ scope.x、$ scope.yを定義しました:
親テンプレート:<myDirective expr="function1(x) + y"></myDirective>

<button ng-click="expr()"></button>呼び出し$scope.function1($scope.x) + $scope.y
<button ng-click="expr({x: 5})"></button>呼び出し$scope.function1(5) + $scope.y
<button ng-click="expr({x:5, y:6})"></button>呼び出し$scope.function1(5) + 6
ディレクティブには、関数として$ scope.myFnがあります:
<button ng-click="expr({function1: myFn, x:5, y:6})"></button>呼び出し$scope.myFn(5) + 6

于 2016-10-20T16:13:48.577 に答える
0

「{{title}}」を「@」で使用し、「title」を「=」で使用する必要があるのはなぜですか?

{{title}}を使用すると、親スコープの値のみがディレクティブビューに渡され、評価されます。これは一方向に制限されているため、変更は親スコープに反映されません。子ディレクティブで行われた変更を親スコープにも反映する場合は、「=」を使用できます。これは双方向です。

要素を属性で装飾せずに、親スコープに直接アクセスすることもできますか?

ディレクティブにスコープ属性が含まれている場合(スコープ:{})、親スコープに直接アクセスすることはできなくなります。ただし、scope。$ parentなどを介してアクセスすることは可能です。ディレクティブからスコープを削除すると、直接アクセスできます。

ドキュメントには、「分離されたスコープから式を介して親スコープにデータを渡すことが望ましい場合が多い」と記載されていますが、双方向バインディングでも問題なく機能するようです。なぜ表現ルートが良いのでしょうか?

コンテキストによって異なります。データを使用して式または関数を呼び出す場合は&を使用し、データを共有する場合は'='を使用して双方向の方法を使用できます。

以下のリンクで、ディレクティブにデータを渡す複数の方法の違いを見つけることができます。

AngularJS –分離されたスコープ– @ vs = vs&

http://www.codeforeach.com/angularjs/angularjs-isolated-scopes-vs-vs

于 2017-06-28T07:42:41.807 に答える
0

@属性文字列バインディング(一方向)=双方向モデルバインディングとコールバックメソッドバインディング

于 2017-11-13T05:39:41.247 に答える
0

@は、ローカル/ディレクティブスコーププロパティをDOM属性の評価値にバインドします。=ローカル/ディレクティブスコーププロパティを親スコーププロパティにバインドします。&バインディングは、ディレクティブ内で呼び出すことができるように、ディレクティブのスコープにメソッドを渡すためのものです。

@属性文字列バインディング=双方向モデルバインディングとコールバックメソッドバインディング

于 2018-06-18T06:36:16.983 に答える