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>> {{$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')
が実行される。