Vue公式ガイド読解メモ-描画関数とJSX その2
今日は「描画関数とJSX」の続き
素の JavaScript によるテンプレートの書き換え
v-if, v-for
v-if, v-forはJavaScriptで普通にif/else/mapなどを使って書き換えられる
<ul v-if="items.length"> <li v-for="item in items">{{ item.name }}</li> </ul> <p v-else>No items found.</p>
props: ['items'], render: function (createElement) { if (this.items.length) { return createElement('ul', this.items.map(function(item) { return createElement('li', item.name) })) } else { return createElement('p', 'No items found') } }
なるほどね、普通のJS記法で分岐とか繰り返しを書いてしまえば良いと。 これも、テンプレートコンパイラのお仕事なのかな。
v-model
render関数に直接的なv-modelの対応はない。 つまり、v-modelがやっていることを自分で実装する必要がある。 ※この自分で実装する部分も、テンプレートからrender関数にコンパイルするときは、スニペットみたいなものが自動生成されているんだろうな。
props: ['value'], render: function(createElement) { var self = this return createElement('input', { domProps: { value: self.value }, on: { input: function(event) { self.$emit('input', event.target.value) } } }) }
なんかよくわからんコードだぞ。
createElement('input')で作ったvnodeのinputイベントにリスナー登録してて、イベントが発生したら、$emit('input')している。
$emit()はVueの機能だから。ネイティブイベントをVueイベントに変換しているイメージか。
domPropsは、domであるinputタグのvalue属性とのひも付きか。self.valueがこのコンポーネント自身が保持するvalueなので、domにコンポーネントのvalueをセットしているよ、ということか。
これは、リアクティブに動作すると思うのだけど、この仕組はもっとコアなものなのかも。(ここには現れない)
event.target.valueをself.valueにセットする仕組みがあるはずなんだよな。多分。それもdomPropsで指定しているから大丈夫なんかな。(違う気がする)
イベントとキー修飾
.passive, .capture, .once イベント修飾子は、onで使用できる接頭辞を提供している。
on: { '!click': this.doThisInCapturingMode, '~keyup': this.doThisOnce, '~!mouseover': this.doThisOnceInCapturingMode }
ほー、onceとかって、一回しかイベント拾わない、みたいなやつだよね。.stopみたいに、event.stopPropagation()と簡単に代替できないから、接頭辞を提供してあげている、ってことかな。
一旦ここまで 次は「スロット」
追記
スロット
this.$slotsで、スロットの内容にアクセスできる。
render : function (createElement) { // <div><slot></slot></div> return createElement('div', this.$slots.default) }
this.$scopedSlotsでvnodeを返す関数として、スコープ付きスロットにアクセスできると。
($scopedSlotsって使われてたのね、もしかして、v-slotが2.6で追加されたけど、render関数は変更が無いのかもしれない)
うーん、スコープ付きとは、slot内のコンテンツで参照できる値を親から渡せるみたいなイメージだよな。
なんで、$slotsと別にあるのか、やっぱりよくわからんな。$slotsに統合されててもいい気がするが。スコープ付きスロットとそうじゃないスロットで区別されているのは、なにか理由があるのか。ちょっと気になる。
今は、そういうものだと思っておこう。
JSX
render関数の中身をガチで実装するのはつらい。 つらいので、JSXで書けるbabelプラグインがあるとのこと。
テンプレートで良い気がするが。。。
new Vue({ el : '#demo', render: function (h) { return ( <AnchoredHeading level={1}> <span>Hello</span> world! </AnchoredHeading> ) } })
なぜわざわざ、render関数を噛ますのか。
createElementをhにエイリアスするのは、Vueのエコシステムの中でよく見かける慣習らしい。たしかに、よく見る。なんでや。
このあたりで終わろう。 次は「関数型コンポーネントから」