Menu

QuickStart 05 - Global Vue API is changed to use an application instance (2021.03.08) - 图1

Why

In vue2, there were two problems:

  • Global configuration makes it easy to accidentally pollute other test cases during testing. The reason is that global apis such as Vue.use and Vue.mixin can cause some effects which are shared among every root instance.
  • Global configuration makes it difficult to share the same copy of a Vue instance between multiple “apps” on the same page, but with different global configurations.

New Global API: createApp

Different from vue2, vue3 has a new concept called app instance instead root instance before.

In vue3, we can call createApp to create an app instance.

  1. import { createApp } from 'vue'
  2. const app = createApp({})

If you use a CDN build of Vue3, you can get createApp api from global Vue object.

  1. const { createApp } from Vue
  2. const app = createApp({})

An app instance contains any APIs that globally mutate Vue’s behavior in vue3. Because of this, global configurations are isolated among app instances.

Here is a table of the Vue2 global APIs and their corresponding instance APIs in vue3:

2.x Global API 3.x Instance API (app)
Vue.config app.config
Vue.config.productionTip removed (see below)
Vue.config.ignoredElements app.config.isCustomElement (see below)
Vue.component app.component
Vue.directive app.directive
Vue.mixin app.mixin
Vue.use app.use (see below)
Vue.prototype app.config.globalProperties (see below)

All other global APIs that do not globally mutate behavior are now named exports, as documented in Global API Treeshaking.

config.productionTip Removed

In vue3, the “use production build” tip will only show up when using the “dev + full build” (the build includes the runtime compiler and has warning).

For ES modules builds, since they are used with bundlers, and in most cases a CLI or boilerplate would have configured the production env properly, this tip will no longer show up.

config.ignoredElements is Now config.isCustomElement

This config option is for supporting native custom elements, so the renaming better conveys what it does. The new option provide a function usage to replace the old string / RegExp approach for for more flexibility:

  1. // vue2.x
  2. Vue.config.ignoredElements = ['costomtable', /^custom-/]
  3. // vue3.x
  4. const app = createApp({})
  5. app.config.isCustomElement = tag => tag.startsWith('custom-')

Important

n Vue 3, the check of whether an element is a component or not has been moved to the template compilation phase, therefore this config option is only respected when using the runtime compiler. If you are using the runtime-only build, isCustomElement must be passed to @vue/compiler-dom in the build setup instead - for example, via the compilerOptions option in vue-loader (opens new window).

  • If config.isCustomElement is assigned to when using a runtime-only build, a warning will be emitted instructing the user to pass the option in the build setup instead;
  • This will be a new top-level option in the Vue CLI config.

Vue.prototype Replaced by config.globalProperties

Vue.prototype was designed to add properties that would be accessible in all child components.

The original intention was good. But in muti-root projects, global configurations can pollute all root instances. This is why creating config.globalProperties. Every properties in it will be only accessible in components within app instances.

A Note for Plugin Authors

In vue2, vue installs a plugin like this in a browser environment:

  1. var inBrowser = typeof window !== 'undefined'
  2. /* ... */
  3. if (inBrowser && window.Vue) {
  4. window.Vue.use(VueRouter)
  5. }

Now Vue.use has been removed. You can use plugins like this:

  1. const app = createApp(MyApp)
  2. app.use(VueRouter)

Mounting App Instance

Mouting app instance:

  1. import { createApp } from 'vue'
  2. import MyApp from './MyApp.vue'
  3. const app = createApp(MyApp)
  4. app.mount('#app')

How to initilize a global component or a directive:

  1. const app = createApp(MyApp)
  2. app.component('button-counter', {
  3. data: () => ({
  4. count: 0
  5. }),
  6. template: '<button @click="count++">Clicked {{ count }} times.</button>'
  7. })
  8. app.directive('focus', {
  9. mounted: el => el.focus()
  10. })
  11. // now every application instance mounted with app.mount(), along with its
  12. // component tree, will have the same “button-counter” component
  13. // and “focus” directive without polluting the global environment
  14. app.mount('#app')

Provide / Inject

  1. // in the entry
  2. app.provide('guide', 'Vue 3 Guide')
  3. // in a child component
  4. export default {
  5. inject: {
  6. book: {
  7. from: 'guide'
  8. }
  9. },
  10. template: `<div>{{ book }}</div>`
  11. }

Share Configurations Among Apps

  1. import { createApp } from 'vue'
  2. import Foo from './Foo.vue'
  3. import Bar from './Bar.vue'
  4. const createMyApp = options => {
  5. const app = createApp(options)
  6. app.directive('focus', /* ... */)
  7. return app
  8. }
  9. createMyApp(Foo).mount('#foo')
  10. createMyApp(Bar).mount('#bar')