functional componentとは
Vue公式 描画関数とJSX
あるのは知っていてなんとなくJSXでReact的(*)な書き方なんだなくらいの知識でした。
これまであまり使う機会がなく、かつqiitaでもあまりないのでなんとなく手を出しづらい感がありましたが、今回Vueしか知らない人でも取り入れやすい使い方からまとめたいと思います。
*Reactは何となくしか分かっていませんが
そもそもVueはテンプレートを使うことが推奨されています。その中でfunctional componentとはナニモノか、それにはまずrendar関数を理解しておくことが必要です。
・公式より
JavaScript による完全なプログラミングパワーを必要するときには、コンパイラに近い 描画 (render) 関数が使用できます。
理解:render関数を使用するとJavaScriptのパワーを解放できるらしい
rendar関数で何をするのか
・公式より
Vue は、実際の DOM に加える必要がある変更を追跡する仮想 DOM を構築することで、これを達成します。
return createElement('h1', this.blogTitle)
上記のようにDOMを生成していく、いわゆるJSXです。
それを省略記法にすると「createElement」が「h」になります。
import AnchoredHeading from './AnchoredHeading.vue'
new Vue({
el: '#demo',
render: function (h) {
return (
<AnchoredHeading level={1}>
<span>Hello</span> world!
</AnchoredHeading>
)
}
})
上記のコンポーネントは状態の管理や渡された状態の watch をしておらず、また、何もライフサイクルメソッドを持っていません。
ここでやっと出てきます
関数型コンポーネント(functional component)
ただし条件付きです。
・状態を持たない (リアクティブデータが無い)
・インスタンスを持たない ( this のコンテキストが無い)
この場合に関数型としてコンポーネントをマークできます
関数型コンポーネント(functional component)
・メリット
関数型コンポーネントは上記のように状態を持たないため、高速に描画ができることがメリットとなります。
・形式
形式は以下のようになります。
Vue.component('my-component', {
functional: true,
props: {
// ...
},
// 2 つ目の context 引数が提供されます。
render: function (createElement, context) {
// ...
}
})
だがしかし、Vueのテンプレートに慣れている人はこれではしんどいわけで
以下のように書けます(※)
※2.5.0以降では、単一ファイルコンポーネントを使用している場合、テンプレートベースの関数型コンポーネントは次のように宣言できます。
<template functional>
<button
class="btn btn-primary"
v-bind="data.attrs"
v-on="listeners"
>
{{ props.title }}
</button>
</template>
やっと見慣れたテンプレートと同じになりました。
ただそのまま同じようにいくかというと違うわけで、その辺をまとめていきます。
テンプレートとの差分
props
propsは {{ props.XXX }}
のように記載する必要があります。
・理由
Vueインスタンスをもっていないので、Vue Loaderはpure JavaScritに変換するため
listeners(data.on)
イベントはlistenersを通して適用することになります。
<button v-on="listeners">Click me</button>
イベントだけなら上記の書き方でも問題ないのですが、パラメータを追加する場合はイベントと一緒に指定して書きます
<Mybutton @click="clickMethod" title="Click me" />
<button @click="listeners.click(1)">{{ props.title }}</button>
attr
属性値の引継ぎはdata.attrs
で行うことができます
<div>
<DisplayDate
:date="'6 Dec 1999'"
aria-label="6 of December of 1999 was a long time ago, but not so much"
/>
</div>
<template functional>
<span v-bind="data.attrs">{{ props.date }}</span>
</template>
class
静的なclass
class指定はdata.staticClass
で引き継げます
<MyTitle
title="Let's go to the mall, today!"
class="super-bold-text"
/>
<span class="span-class" :class="data.staticClass">
{{ props.title }}
</span>
// ⇒ <span class="span-class super-bold-text">
動的なclassとのマージ1
<MyTitle
title="Let's go to the mall, today!"
class="super-bold-text"
:some-prop="true"
/>
<span class="span-class" :class="[data.staticClass, { 'another-class': props.someProp }]">
{{ props.title }}
</span>
// ⇒ <span class="span-class super-bold-text another-class">
動的なclassとのマージ2
<MyTitle
title="Let's go to the mall, today!"
class="super-bold-text"
:class="'another-class'"
/>
<span class="span-class" :class="[data.staticClass, data.class]">
{{ props.title }}
</span>
// ⇒ <span class="span-class super-bold-text another-class">
おわり
差分についてコンポーネント利用は「inject」を使うとか、「slots」とか「children」とかあるみたいですが、とりあえず今回はここまでとしたいと思います。
続き
Vue functional componentでのmethods,filter
https://qiita.com/ryuseiyarou/items/58766b01f561d94532ad