Nue.jsはリアクティブではないという事を理解しよう[話題のUIライブラリ]
Nue.jsは軽量ながらreactやvueの代替になるライブラリとして公開され、最近話題になっています。この記事では、Nue.jsの根幹になる部分の注意点について紹介したいと思います。
Nue.jsとは
Nue.jsはRiot.jsというUIライブラリの制作に関わっていた方が作成した新しいUIライブラリです。私自身、Riot.jsが大好きで、利用者が減っても引き続き利用し記事など色々書いていました。そのため、Nue.jsがどのような思想で作られているのか興味があり触ってみました。その中でRiot.jsの思想を強く引き継いでいるなと感じた部分がテンプレート上の値の更新方法です。
Nue.jsはリアクティブではない
ReactやVueやSvelteの場合、定義したリアクティブな変数を変更すると自動でテンプレート上の値が更新されていたと思います。しかしNue.jsでは定義した値を変更しただけでは自動的に更新されません。それはなぜなのか?その仕組みの違いをサンプルを使って説明していきます。
Vue.jsでのサンプル
setInterval
で一秒おきにリアクティブ変数titleにxを追記するというコードです。リアクティブなので参考動画では1秒毎に文字が追記されるのがわかると思います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<vue-component> <div :class="'length'+title.length">title: {title}</div> <button @click="console.log('click!')">click</button> <script> export default { setup(){ const tpl = {title: Vue.ref('x')}; setInterval(function(){ tpl.title.value += 'x'; console.log('title: '+tpl.title.value); }, 1000); return tpl; } } </script> </vue-component> |
実行結果動画
Nue.jsのサンプル1
一秒おきに変数titleにxを追記するというコードです。しかしリアクティブでないため参考動画では1秒毎に文字が追記されず、ボタンをクリックした時にだけテンプレートの表示が更新されているのがわかると思います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<div @name="nue-component" class="parent"> <div class="length{title.length}">title: {title}</div> <button @click="console.log('click!')">click</button> <script> title = 'x'; mounted() { let self = this; setInterval(function(){ self.title += 'x'; console.log('title: '+self.title); }, 1000); } </script> </div> |
実行結果動画
なぜ表示が更新されない?
理由はNue.jsにはデータの更新を検知する仕組み(リアクティブ)が導入されていないためです。値が変わっても気づかず、表示が更新されません。ではどうやっでテンプレートを更新するかと言うと、コンポーネントインスタンスが持っているupdate()
というメソッドを実行します。そうするとテンプレート内で使われている値が再計算され最新の表示に更新されます。
ちなみに、このupdate()メソッドはテンプレートで指定されたイベントハンドラ(@clickなど)が実行された場合には終了時に自動的に実行されます。それによりクリックして数値を変更したいといった場合は何も考えずともテンプレートが更新されるのです。(逆に値が変わっていなくても再計算されてしまう)
しかし、このサンプルのようにイベントハンドラを介さない値の変更については手動でupdate()メソッドを実行しないとテンプレートが再計算されません。ではこのサンプルにupdate()メソッドを追加して、値の更新直後にテンプレートも更新されるようにしてみたいと思います。
update()で更新させる
Nue.jsのサンプル2(改良版)
毎回update()を実行するようにすると毎回表示が更新されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<div @name="nue-component" class="parent"> <div class="length{title.length}">title: {title}</div> <button @click="console.log('click!')">click</button> <script> title = 'x'; mounted() { let self = this; setInterval(function(){ self.title += 'x'; console.log('title: '+self.title); }, 1000); self.update(); } </script> </div> |
実行結果動画
nue.jsを使う場合は、このようにいつupdate()メソッドが実行されているか理解しておく必要があるのです。
結び
riot.jsではriot.settings.autoUpdate
という設定値があり、これをfalseにしておくとイベントハンドラ実行時も勝手にupdate()メソッドを実行させないという事が可能で、毎回手動で実行するようにしていました。こうすることで無駄な更新回数を減らしパフォーマンスを追求することが出来たりもしたのですが、最近はデータの管理が手に余るようになりキツさを感じていました。そうしてvue.jsに移行し、リアクティブなふるまいの便利さにも慣れてきたので、「今更この手法に戻るのもなぁ」というのが正直な感想です。しかし未だ興味はありますので反響をいただけばnueとvunの比較記事など書きたいと思います。またnueの仕様の間違いもありましたらコメントいただければと思います。