Edited at

AngularJS1.5の scope, bindingsで指定する @=&< の仕様を見直す

More than 3 years have passed since last update.

AngularJS1.5 では、scope, bindings 指定時に @=& に加えて、< を指定できるようになった。< について追加で理解するとともに、=& を正しく理解していない側面があったため、まとめてみることにした。

$compile のドキュメントを参考にしました。

というわけでテスト書いて動作を試してみる。せっかくなので、AngularJS1.5から出たComponentを使う。

const app = angular.module('myApp', []);

class Widget {
constructor() {
this.name = 'Soba';
}

changeName() {
if (this.name == 'Soba') {
this.name = 'Udon';
} else {
this.name = 'Soba';
}
}
}

app.component('widget', {
template: '<div>Hello world, {{$ctrl.name}}</div>'+
'<button ng-click="$ctrl.changeName()">Change Name</button>'+
'<child-widget name-at="Hi, {{$ctrl.name}}" name-eq="$ctrl.name" name-gt="$ctrl.name"></child-widget>',
controller: Widget
});

class ChildWidget {
changeNameAt() {
this.nameAt = 'Yakisoba';
}

changeNameEq() {
this.nameEq = 'Yakisoba';
}

changeNameGt() {
this.nameGt = 'Yakisoba';
}
}

app.component('childWidget', {
controller: ChildWidget,
template: '<div>@ {{$ctrl.nameAt}}</div>' +
'<div>= {{$ctrl.nameEq}}</div>' +
'<div>&gt; {{$ctrl.nameGt}}</div>' +
'<button ng-click="$ctrl.changeNameAt()">Change nameAt</button>' +
'<button ng-click="$ctrl.changeNameEq()">Change nameEq</button>' +
'<button ng-click="$ctrl.changeNameGt()">Change nameGt</button>',
bindings: {
'nameAt': '@',
'nameEq': '=',
'nameGt': '<'
}
});

以下でテスト可能

https://jsfiddle.net/kawahara/we8k5x3f/4/


@



  • @ は、DOM属性に渡した情報が文字列として渡る

  • 内容については、HTMLと同じく $parse を通して解釈される。 name に Kawahara が入っていた場合 Hi, {{name}} とした時は、Hi, Kawahara が渡る。 name が別のものに変わった場合は別の文字に更新される。


  • $parse の必要のない固定の文字情報だったら、$attrs から情報取得したほうがいいのかな。


=


  • 双方向データバインディング

  • 親スコープからの変更は子スコープに伝搬され、子スコープの変更は親スコープに伝搬させる関係になる。


=?


  • 双方向なので、親スコープが情報なしの状態で、子スコープ側で変更が加わると、通常はエラーが発生するようになっている。? を指定すると、データを親から渡す挙動がオプションとなる。(エラーが抑制される。)


=*


  • 通常ではオブジェクトの変更トラッキングには、$watch を使っているが、 $watchCollection を使うような挙動に変わる。

  • 前述の ? と併用する場合は =?* のような書き方となる。

  • 正直、使いどころがよくわからん。。誰か教えて下さい。 https://teratail.com/questions/30528


<


  • 1.5から新しく追加された 単方向データバインディング (原文ではone-way bindingと記されている) と言われるもの。

  • 親スコープからの変更は子スコープに伝搬させるが、子スコープの変更は親スコープに伝搬させない特性を持っている。


<?



  • =? の単方向データバインディングバージョン。


  • ? 指定なし、親からのデータ渡しなしの状態で、子スコープの値を変更をしても、= のようにエラーはおきたりなどはしない。

  • コード見る限りは、余計な処理が走らなくなるので、親から値を渡さないことがあるのであれば、ぜひ指定しておくべき。


&


  • 子スコープには、&で指定した式を実行するための関数が渡る。

  • 実行可能な式を書けばいいので $ctrl.flag = true のような情報を渡す式を書いてもよい。

  • 親スコープ上で doSomething(data) を指定したときに、子スコープ上で doSomething({data: 'aaa'}) 実行すると、doSomething('aaa') が実行される。