# グローバル API
breaking
Vue 2.x では、グローバルに Vue の振る舞いを変更するグローバル API や設定が多数ありました。例えば、グローバルコンポーネントを登録するには、 以下のような Vue.component
API を使用します:
Vue.component('button-counter', {
data: () => ({
count: 0
}),
template: '<button @click="count++">Clicked {{ count }} times.</button>'
})
2
3
4
5
6
同様に、以下のようにグローバルなディレクティブを宣言できました:
Vue.directive('focus', {
inserted: el => el.focus()
})
2
3
この方法は便利でしたが、いくつか問題がありました。Vue 2 では、内部的には "app" (アプリケーション) の概念がありませんでした。私達が アプリケーションとして定義していたものは、単に new Vue()
で生成された ルート Vue インスタンス でした。同じ Vue コンストラクタから作成された root インスタンスは、同じグローバル設定を共有します。その結果として:
グローバル設定を使用することで、テスト中に他のテストケースを誤って汚染しやすくなってしまいました。ユーザーは元のグローバル設定を保存し、各テスト後に元に戻すことを注意深くやる必要がありました (例
Vue.config.errorHandler
のリセット)。Vue.use
や、Vue.mixin
のような API は、影響を元に戻す方法もありません。このため、プラグインを含むテストは特に厄介でした。実際、vue-test-utils はそれらに対応するためにcreateLocalVue
という特別な API を作らなければなりませんでした:import { createLocalVue, mount } from '@vue/test-utils' // 拡張した `Vue` コンストラクタを作成 const localVue = createLocalVue() // "ローカル" Vue コンストラクタに、"グローバル" にプラグインをインストール localVue.use(MyPlugin) // `localVue` をマウントオプションに渡す mount(Component, { localVue })
1
2
3
4
5
6
7
8
9
10また、グローバル設定では、同じページ上の複数のアプリケーション間でグローバル設定が異なる Vue のコピーを共有することが困難でした。
// 以下は両方のルートインスタンスに影響を及ぼします Vue.mixin({ /* ... */ }) const app1 = new Vue({ el: '#app-1' }) const app2 = new Vue({ el: '#app-2' })
1
2
3
4
5
6
7
これらの問題を回避するために、Vue 3 では、以下のような API を導入しました。
# 新しいグローバル API: createApp
createApp
の呼び出しでは、 Vue 3 の新しい概念である アプリケーションインスタンス を返します。
import { createApp } from 'vue'
const app = createApp({})
2
3
Vue の CDN ビルドを使っている場合、 createApp
はグローバルな Vue
オブジェクトを介して公開されます:
const { createApp } = Vue
const app = createApp({})
2
3
アプリケーションインスタンスは、 Vue 2 のグローバル API のサブセットを公開します。おおまかには、Vue の振る舞いをグローバルに変更する全ての API は、アプリケーションインスタンスに移されます 。こちらは、 Vue 2 のグローバル API とインスタンス API との対応表です:
2.x グローバル API | 3.x インスタンス API (app ) |
---|---|
Vue.config | app.config |
Vue.config.productionTip | 削除 (以下を参照) |
Vue.config.ignoredElements | app.config.isCustomElement (以下を参照) |
Vue.component | app.component |
Vue.directive | app.directive |
Vue.mixin | app.mixin |
Vue.use | app.use (以下を参照) |
Vue.prototype | app.config.globalProperties (以下を参照) |
グローバルに振る舞いを変更しないその他のグローバル API は グローバル API の Treeshaking にあるように、名前付きエクスポートになりました。
# config.productionTip
の削除
Vue 3.x では "use production build" のヒントは、"dev + full build" (ランタイムコンパイラを含み、警告があるビルド) を使用しているときにのみ表示されます。
ES Modules ビルドでは、モジュールバンドラーと一緒に使用されていることと、ほとんどの場合 CLI やボイラープレートで本番環境が適切に設定されているため、このヒントは表示されなくなりました。
# config.ignoredElements
は config.isCustomElement
に変更
この設定オプションはネイティブのカスタム要素をサポートする意図で導入されたため、それがわかるように名前に変更しました。新しいオプションでは、以前の 文字列 / RegExp の方法より、柔軟な方法を提供する関数を期待します。
// before
Vue.config.ignoredElements = ['my-el', /^ion-/]
// after
const app = createApp({})
app.config.isCustomElement = tag => tag.startsWith('ion-')
2
3
4
5
6
重要
Vue 3 では、要素がコンポーネントであるかどうかのチェックはコンパイルフェーズに移されたため、この設定はランタイムコンパイラを使用しているときにのみ尊重されます。ランタイム限定のビルドを使用している場合は、代わりにビルド設定で isCustomElement
を @vue/compiler-dom
に渡す必要があります - 例えば compilerOptions
option in vue-loader (opens new window) で。
- ランタイム限定ビルド使用時に、
config.isCustomElement
が代入された場合、ビルドの設定でこのオプションを設定するように警告が表示されます。 - これは、Vue CLI 設定の新しいトップレベルのオプションになります。
# Vue.prototype
は config.globalProperties
と置換
Vue 2 では、すべてのコンポーネントでアクセス可能なプロパティを追加するために、 Vue.prototype
がよく使われていました。
Vue 3 では、 config.globalProperties
が同様のものです。これらのプロパティは、アプリケーション内でコンポーネントをインスタンス化する際にコピーされます:
// before - Vue 2
Vue.prototype.$http = () => {}
2
// after - Vue 3
const app = createApp({})
app.config.globalProperties.$http = () => {}
2
3
また globalProperties
の代わりに provide
(後述) を使うことも考えられます。
# プラグイン作者へのノート
プラグイン作者の一般的なプラクティスとして、Vue.use
を使ってプラグインを自動的に UMD ビルドにインストールさせるものがありました。例えば、公式の vue-router
プラグインのブラウザ環境へのインストールは以下のようになっていました:
var inBrowser = typeof window !== 'undefined'
/* … */
if (inBrowser && window.Vue) {
window.Vue.use(VueRouter)
}
2
3
4
5
use
グローバル API は、Vue 3 では利用できなくなったので、このメソッドは動作しなくなり、 Vue.use()
の呼び出しは警告が出るようになりました。その代わりに、エンドユーザーはアプリケーションのインスタンスでプラグインを使用することを明示的に指定する必要があります。
const app = createApp(MyApp)
app.use(VueRouter)
2
# アプリケーションインスタンスのマウント
createApp(/* オプション */)
で初期化した後、アプリケーションインスタンス app
は、app.mount(domTarget)
を使ってルートコンポーネントインスタンスをマウントできます。
import { createApp } from 'vue'
import MyApp from './MyApp.vue'
const app = createApp(MyApp)
app.mount('#app')
2
3
4
5
これらの変更によって、このガイドの初めにあるコンポーネントとディレクティブの例は以下のように書き換えられます:
const app = createApp(MyApp)
app.component('button-counter', {
data: () => ({
count: 0
}),
template: '<button @click="count++">Clicked {{ count }} times.</button>'
})
app.directive('focus', {
mounted: el => el.focus()
})
// このようにして、app.mount() でマウントされた全てのアプリケーションインスタンスは、
// グローバル環境を汚染すること無く、同じ "button-counter" コンポーネントと
// "focus" ディレクティブを持つようになりました。
app.mount('#app')
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Provide / Inject
Vue 2.x のルートインスタンスで provide
オプションを使用するのとどうように、Vue 3 のアプリケーションインスタンスでも、アプリケーション内の任意のコンポーネントに注入できる依存関係を提供できます:
// エントリー
app.provide('guide', 'Vue 3 Guide')
// 子コンポーネント
export default {
inject: {
book: {
from: 'guide'
}
},
template: `<div>{{ book }}</div>`
}
2
3
4
5
6
7
8
9
10
11
12
provide
を使うことは、特にプラグインを書くときに、 globalProperties
の代わりになります。
# アプリケーション間での設定の共有
コンポーネントや、ディレクティブの設定をアプリケーション間で共有する方法の一つとして、以下のようなファクトリ関数があります:
import { createApp } from 'vue'
import Foo from './Foo.vue'
import Bar from './Bar.vue'
const createMyApp = options => {
const app = createApp(options)
app.directive('focus', /* ... */)
return app
}
createMyApp(Foo).mount('#foo')
createMyApp(Bar).mount('#bar')
2
3
4
5
6
7
8
9
10
11
12
13
このようにして、 fucus
ディレクティブは Foo
と Bar
両方のインスタンスとその子で有効になります。