25
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

JSXに慣れないVue利用者のfunctional component

Last updated at Posted at 2019-12-15

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を通して適用することになります。

childComponent
<button v-on="listeners">Click me</button>

イベントだけなら上記の書き方でも問題ないのですが、パラメータを追加する場合はイベントと一緒に指定して書きます

parentComponent
<Mybutton @click="clickMethod" title="Click me" />
childComponent
<button @click="listeners.click(1)">{{ props.title }}</button>

attr

属性値の引継ぎはdata.attrsで行うことができます

parentComponent
<div>
  <DisplayDate
    :date="'6 Dec 1999'"
    aria-label="6 of December of 1999 was a long time ago, but not so much"
  />
</div>
childComponent
<template functional>
  <span v-bind="data.attrs">{{ props.date }}</span>
</template>

class

静的なclass

class指定はdata.staticClassで引き継げます

parentComponent
<MyTitle
  title="Let's go to the mall, today!"
  class="super-bold-text"
/>
childComponent
<span class="span-class" :class="data.staticClass">
  {{ props.title }}
</span>
// ⇒ <span class="span-class super-bold-text">

動的なclassとのマージ1

parentComponent
<MyTitle
  title="Let's go to the mall, today!"
  class="super-bold-text"
  :some-prop="true"
/>
childComponent
<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

parentComponent
<MyTitle
  title="Let's go to the mall, today!"
  class="super-bold-text"
  :class="'another-class'"
/>
childComponent
<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

25
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?