在这篇文章中,咱们将首先看看Vue 2应用程序中的应用程序初始化代码是如何工作的。而后咱们会看到它有哪些毛病,以及如何通过Vue框架第3版中应用的新初始化语法打消这些毛病。
咱们先说说目前Vue 2中的初始化形式。通常,在 src/main.js
文件中,咱们是通过调用一个新的Vue作为创立利用实例的构造函数来疏导利用的。
import Vue from "vue";import App from "./App.vue";import router from './router'import SomeComponent from '@/components/SomeComponent.vue'import SomePlugin from '@/plugins/SomePlugin'const vue2AppCopy = new Vue({ router, render: h => h(App)});vue2AppCopy.component('SomeComponent',SomeComponent);vue2AppCopy.use(SomePlugin);vue2AppCopy.$mount('#app')
这个利用实例将在咱们SPA的整个生命周期内为所有的逻辑服务。这所有都很好,大概3年来,咱们始终应用这种语法来疏导咱们的Vue应用程序。
然而,在Vue 3中,初始化代码语法已更改。首先让咱们看一下新语法,而后再看一下应用它的益处。
新的Vue 3 createApp办法
在Vue 3中,咱们有一个专门的 createApp
函数来实现这一点。createApp函数以一个根组件(App.vue
)作为参数,并返回一个Vue利用实例。因而,最简略的利用初始化如下所示:
import { createApp } from 'vue'import App from './App.vue'createApp(App).mount('#app')
createApp返回的Vue应用程序实例也称为应用程序上下文对象。这个对象能够用来在疏导过程中进一步为利用增加更多的性能。上面是一个更高级的初始化代码示例:
import { createApp } from 'vue'import App from './App.vue'import router from './router'import SomeComponent from '@/components/SomeComponent.vue'import SomePlugin from '@/plugins/SomePlugin'const myV3App = createApp(App)myV3App.component('SomeComponent', SomeComponent)myV3App.use(SomePlugin).use(router)// add more functionality to myV3App// now we're ready to mountmyV3App.mount('#app')
与V2相比,在增加额定的逻辑(例如插件和组件)方面没有太大变动,对吗?
您能够在Vue 3文档中找到受反对办法的残缺概述。
这很好,但有一个小小的但很重要的变动——咱们应用了一个专门的函数,而不是 new Vue
实例。
//v2const vue2App = new Vue({}) // Working with the main Vue instace//v3const myV3App = createApp(App).mount('#app') // Create a copy of the Vue instance
那么,为什么应用新的专用 createApp
函数比应用 new Vue
构造函数更好呢?
Vue 3初始化代码的益处
在Vue 2应用程序初始化代码中,咱们应用了从库中导入的Vue对象来创立此应用程序实例以及所有其余新的应用程序实例。
应用这种办法,不可能将一些性能仅隔离到一个Vue实例中,因为Vue应用程序依然应用从库中导入的同一个Vue对象。
为了演示这一点,让咱们看看上面的例子——正如你所看到的,vue2AppOne
和 vue2AppTwo
都能够拜访一个名为 myDirective
的指令:
Vue.directive('myDirective', { /* ... */})Vue.component({ /* ... */})const vue2AppOne = new Vue(/**/).mount('#app1')const vue2AppTwo = new Vue(/**/).mount('#app1')
在一个网站或应用程序中创立多个Vue应用程序可能并不常见。
但随着我的项目规模的扩充,由不同的团队开发,以及前台微服务的风行,你可能会在某个时候发现自己也在这样做。
而后,简直不可能应用v2语法取得另一个具备不同性能的Vue实例。
Vue 3中的新语法容许咱们将每个应用程序的配置作为一个独自的自定义对象,因为应用程序是应用专用函数(createApp
)来创立独立实例的。
新的体系结构使咱们能够领有两个或更多孤立的Vue实例,默认状况下它们不共享任何个性,即便它们是在一个文件中创立的。
然而,如果你想在两个实例之间共享一些性能,你能够!在上面的例子中,vue3AppOne
和 vue3AppTwo
共享 LocalePlugin
,但不共享 searchchinputcomponent
。
const config = {/* some global config */}const vue3AppOne = Vue.createApp(config)vue3AppOne.component('SearchInput', SearchInputComponent)vue3AppOne.use(LocalePlugin)const vue3AppTwo = Vue.createApp(config)vue3AppTwo.use(LocalePlugin)
为了演示这种行为,咱们用2个简略的Vue 3实例创立了一个代码仓库,因为应用了新的 createApp
语法,这些实例不共享组件和指令。请看一下它在本地的玩法。
在配套的仓库中,咱们在一个页面模板的两个不同容器中初始化了两个Vue 3应用程序,见public/index.html。
<div id="header-app"></div><div id="main-app"></div>
一个应用程序将作为一个绝对简略的header标记,而另一个将可能应用router并与store单干。
应用Vue 3语法,咱们能够轻松地在src/main.js文件的初始化代码中将它们离开:
import { createApp } from 'vue'import App from './App.vue'import Header from './Header.vue'import router from './router'import store from './store'createApp(App) .use(store) .use(router) .mount('#main-app')createApp(Header) .mount('#header-app')
如果您应用 vue serve
运行应用程序,您应该可能看到两个局部在一个页面上工作。在控制台输入中,您将看到Main应用程序能够应用 Vuex
拜访 vue-router
和商店,而Header应用程序则不能。
created () { console.log('Hello from Main app') console.log('Main app router', this.$route) console.log('Main app store:', this.$store)}
一个更间接的测试设置
如果您正在应用 vue-test-utils
(版本<2.0.0)为您的Vue 2组件编写测试,您可能会遇到须要应用 createLocalVue
办法来防止净化全局Vue实例的状况。
在咱们的测试场景中存在与Vue 2应用程序中雷同的潜在问题。当咱们增加组件、插件等时,会净化全局Vue实例,而且它们都与每个可用的Vue实例共享。
要解决这个问题,咱们必须应用 createlocalvalue
,它(您曾经猜到了)创立一个新的孤立的本地Vue实例。
import { createLocalVue, mount } from '@vue/test-utils'import MyPlugin from '@/plugins/MyPlugin'const localVueForTest = createLocalVue()localVueForTest.use(MyPlugin)mount(Component, { localVueForTest})
这在Vue 3中不再是一个问题,因为所有的利用扩大:插件、mixins和全局组件都不会扭转全局Vue实例。因而,当在Vue 3中应用vue-test-utils
(版本> = 2.0.0)时,测试文件中的应用程序初始化代码将如下所示:
import { createStore } from 'vuex'import { mount } from '@vue/test-utils'import App from '@/App'import MyPlugin from '@/plugins/MyPlugin'const wrapper = mount(App, { global: { plugins: [MyPlugin] }})