# Render 関数 API
breaking

# 概要

この変更は <template> の利用には影響しません。

以下が変更の簡単な概要になります:

  • h は render 関数の引数ではなく、グローバルにインポートされます。
  • render 関数の引数はステートフルコンポーネントと関数型コンポーネントの間でより一貫性があるものに変更されました。
  • VNode のプロパティの構造がフラットになりました。

詳しい情報は以下を読んでください。

# Render 関数の引数

# 2.x での構文

2.x では、 render 関数は自動的に h 関数(createElement の従来のエイリアス)を引数として受け取るようになっていました:

// Vue 2 の Render 関数の例
export default {
  render(h) {
    return h('div')
  }
}
1
2
3
4
5
6

# 3.x での構文

3.x では、 h は自動的に引数に渡されるのではなくグローバルにインポートされます。

// Vue 3 の Render 関数の例
import { h } from 'vue'

export default {
  render() {
    return h('div')
  }
}
1
2
3
4
5
6
7
8

# Render 関数のシグネチャの変更

# 2.x での構文

2.x では、 render 関数は自動的に h として引数を受け取っていました。

// Vue 2 の Render 関数の例
export default {
  render(h) {
    return h('div')
  }
}
1
2
3
4
5
6

# 3.x での構文

3.x では、 render 関数がなんの引数も受け取らなくなるので、主に setup() 関数の中で利用されます。この変更は setup() 関数に渡された引数だけでなく、スコープの中で宣言されたリアクティブな状態や関数にアクセスできるという追加の利点があります。

import { h, reactive } from 'vue'

export default {
  setup(props, { slots, attrs, emit }) {
    const state = reactive({
      count: 0
    })

    function increment() {
      state.count++
    }

    // render 関数を返す
    return () =>
      h(
        'div',
        {
          onClick: increment
        },
        state.count
      )
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

setup() がどう動作するかについての詳しい情報は、コンポジション API ガイドを参照してください。

# VNode のプロパティの形式

# 2.x での構文

2.x では、VNode のプロパティの中に domProps がネストされたリストとして含まれていました:

// 2.x
{
  staticClass: 'button',
  class: {'is-outlined': isOutlined },
  staticStyle: { color: '#34495E' },
  style: { backgroundColor: buttonColor },
  attrs: { id: 'submit' },
  domProps: { innerHTML: '' },
  on: { click: submitForm },
  key: 'submit-button'
}
1
2
3
4
5
6
7
8
9
10
11

# 3.x での構文

3.x では、全ての VNode のプロパティ構造はフラットになりました。上記の例が下記のようになります。

// 3.x での構文
{
  class: ['button', { 'is-outlined': isOutlined }],
  style: [{ color: '#34495E' }, { backgroundColor: buttonColor }],
  id: 'submit',
  innerHTML: '',
  onClick: submitForm,
  key: 'submit-button'
}
1
2
3
4
5
6
7
8
9

# 登録済みコンポーネント

# 2.x での構文

2.x では、コンポーネントが登録されていた場合、コンポーネントの名前を文字列として第 1 引数に渡すと、 Render 関数がうまく動作します:

// 2.x
Vue.component('button-counter', {
  data() {
    return {
      count: 0
    }
  }
  template: `
    <button @click="count++">
      Clicked {{ count }} times.
    </button>
  `
})
export default {
  render(h) {
    return h('button-counter')
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 3.x での構文

3.x では、 VNodes がコンテキストフリーになったため、登録されているコンポーネントを暗黙的に探すために、文字列 ID を使うことができなくなります。代わりに、 resolveComponent メソッドを使う必要があります:

// 3.x
import { h, resolveComponent } from 'vue'
export default {
  setup() {
    const ButtonCounter = resolveComponent('button-counter')
    return () => h(ButtonCounter)
  }
}
1
2
3
4
5
6
7
8

詳細については、 Render 関数 API の変更に関する RFC (opens new window) を見てください。

# 移行の戦略

移行ビルドのフラグ: RENDER_FUNCTION

# ライブラリの著者

h がグローバルにインポートされるということは、Vue コンポーネントを含むライブラリはどれも import { h } from 'vue' という記述がどこかに含まれていることを意味します。結果として、ライブラリの著者はビルドにおいて適切に Vue の外部化を設定することが求められるので、少し手間が増えます:

  • Vue はライブラリの中にバンドルされるべきではない
  • モジュール向けのビルドでは、インポートはそのまま残されてエンドユーザのバンドラーで処理されるべきです。
  • UMD / ブラウザー環境向けのビルドでは、まずグローバルの Vue.h を試して、フォールバックとして require を呼ぶべきです。

# 次のステップ

Render 関数ガイド でもっと詳しいドキュメントを参照してください!