275
258

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.

【Vue.js】コンポーネントのtemplateの書き方まとめ

Last updated at Posted at 2017-11-06

大きく以下の4つの書き方があります(もっとあるかも)

  1. 文字列
  2. X-template
  3. .vue コンポーネント
  4. 描画関数

1.文字列

一番スタンダードな方法と言えるでしょう。
文字通り文字列で記述します。

Vue.component('my-component', {
  template: '<div>A custom component!</div>'
})

また、tipsですがES6以上なら `` で囲むことによって複数行にまたがって記述することができるので可読性が上がります。

ダブルクオート使うメリットもないはずなので、とりあえずこっち使っとくのがよいのではと思います。

Vue.component('my-component', {
  template: `<div>
              A custom component!
             </div>`
})

そしてこちらの解説に詳しいんですが、
いくつかのタグには制約(例えば<ul>タグの直下にはliしか表示できない、みたいな)が存在しており、
それをエラーとして検出できるのはこの記述方法のみとのことです。
おかしなDOMを作ることを検知できるのは一つのメリットかもしれません。

2.X-template

参照:https://jp.vuejs.org/v2/guide/components.html#x-template

こんな感じでHTML内に定義して

<script type="text/x-template" id="my-component">
  <div>A custom component!</div>
</script>

JSからはID指定で読み込むことができます。

Vue.component('my-component', {
  template: '#my-component'
})

JS内からはID指定するのみなので大分さっぱりします。
ただドキュメントでも言及されている通り、テンプレートの記述がコンポーネントから分離されて
管理が煩雑になりそうなので、プロダクションで使うには良い選択肢ではなさそうです。

3..vue コンポーネント

参考:vue.jsのcomponentをwebpackで.vueにして単一ファイルコンポーネントにする

.vueの拡張子のファイルを作成し、下記のようにtemplateを記述します。

my-component.vue
<template>
  <div>A custom component!</div>
</template>

JSからは以下のように読み込めます。

import MyComponent from './my-component.vue';

new Vue({
  el: '#example',
  components: { MyComponent },
  template: '<my-component>'
})

メリットについては上記の参考記事にすごくよくまとまっているので、是非ご参照ください。
個人的にはこの書き方が一番幸せになれそうな予感がしています。

4.描画関数

参照: https://jp.vuejs.org/v2/guide/render-function.html
厳密にはtemplateの書き方ではなくtemplateを代替するものという捉え方の方が適切っぽいです。

ドキュメントの例をそのまま拝借します。
下記のようなHTMLの構成のコンポーネントを作成、また、h*タグ の数字の部分をコンポーネントのpropsのlevelによって決めたいとします。

<h1> <!-- ここをlevelによって変動させたい -->
  <a name="hello-world" href="#hello-world">
    Hello world!
  </a>
</h1>

愚直にtemplateでやろうとすると下記のようになってしまいます

<script type="text/x-template" id="anchored-heading-template">
  <h1 v-if="level === 1">
    <slot></slot>
  </h1>
  <h2 v-else-if="level === 2">
    <slot></slot>
  </h2>
  <h3 v-else-if="level === 3">
    <slot></slot>
  </h3>
  <h4 v-else-if="level === 4">
    <slot></slot>
  </h4>
  <h5 v-else-if="level === 5">
    <slot></slot>
  </h5>
  <h6 v-else-if="level === 6">
    <slot></slot>
  </h6>
</script>

いかにも冗長ですね。
これをRender関数を使えば以下のように書けます。

Vue.component('anchored-heading', {
  render: function (createElement) {
    return createElement(
      'h' + this.level,   // タグ名
      this.$slots.default // 子の配列
    )
  },
  props: {
    level: {
      type: Number,
      required: true
    }
  }
})

また、Babelプラグインを使えば以下のようにJSXで記述することもできるみたいです。

import AnchoredHeading from './AnchoredHeading.vue'

new Vue({
  el: '#demo',
  render (h) {
    return (
      <AnchoredHeading level={1}>
        <span>Hello</span> world!
      </AnchoredHeading>
    )
  }
})

よりプログラマブルにDOMの中身を出し分けたいという場合に描画関数が適している状況もありそうです。
ちょっと私の経験では動的にタグ名とかを書き換えたい、の様などうしても動的に出し分けないと辛いみたいな要求に出会ったことがないので、文字列でサクッと書くことに比べた有用性がイメージしづらいですが、知識として知っておいて損はない書き方かなと感じました。

275
258
1

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
275
258

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?