今回ご紹介するのは preventUpdate という riot 独自のイベントパラメーター。
<todo>
<input type="text" name="new">
<input type="button" value="add" onclick={add}>
<ul>
<li each={text, i in list}>{text}</li>
</ul>
<script>
this.list = [];
add() {
this.list.push(this.new.value);
}
</script>
</todo>
こちらのinputの文字列をひたすらリストにしていくやつを例に使います。
これ、動きます(そりゃそうでしょうが)。
ただ、ここで疑問がわくわけです。
いつアップデート(再描画)されたんだ??
描画を再更新するのは
明示的に自身の update
関数を発火させるか、親が update
されたタイミングです。
ですが、上記のサンプルでは update
関数も発火してなければ、親でもありません(上記はrootの想定です)。
ではどこで呼ばれたのか。
答えは onclick イベントです
riotでは上記のように on***
でDOMイベントを設定できますが
通常の addEventListener
を用いて自身でイベントを設定した場合とここが異なります。
ためしに、テンプレート内でonclickを用いず、自前でイベントを設定したものをかいてみましょう。
<todo>
<input type="text" name="new">
<input type="button" name="btn_add" value="add">
<ul>
<li each={text, i in list}>{text}</li>
</ul>
<script>
this.list = [];
add() {
this.list.push(this.new.value);
this.update();
}
this.on('mount', function () {
this.btn_add.addEventListener('click', this.add, false);
});
this.on('unmount', function () {
this.btn_add.removeEventListener('click', this.add, false);
});
</script>
</todo>
mount
時とunmount
時にイベントの処理を書いた以外で変更したのは、add
関数で明示的にupdate
を発火させている点です。
これ、update
を発火させないといつまで経っても再描画されません(リストが増えていきません)。
これが、DOMイベントをテンプレート内で設定した場合と、自前で設定した場合の大きな違いです。
そして、テンプレートに描いたほうがコード量も減るし、イベントのremove忘れもなくなるし、いいことづくめだ! と思うのですが、ここでさらに疑問がわきます。
毎回 update が発火しちゃうの??
勝手に更新されてうれしい時もあれば、無駄に毎回updateされたら困る場合も多々あります。
例えば mousemove とか resize とか 発火回数が多いイベントならなおのこと。
再描画が頻発するとパフォーマンスにも影響してきます。
そこで登場するのがお待ちかね preventUpdate です。
使い方は簡単。
add(e) {
e.preventUpdate = true;
// something to do
}
これだけ。
気をつけなければいけないのは、おなじみ preventDefault
が関数なのに対して
preventUpdate
はプロパティなので、くれぐれも e.preventUpdate()
としないように。
これをすることで update
が発火されなくなります。
大量に発生するイベントや、イベント発生とは非同期で update を発火させたい場合に活用していきましょう。