新的Vue 3 應用程式初始化程式碼的好處

語言: CN / TW / HK

在這篇文章中,我們將首先看看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 mount
myV3App.mount('#app')

與V2相比,在新增額外的邏輯(例如外掛和元件)方面沒有太大變化,對嗎?

您可以在 Vue 3文件 中找到受支援方法的完整概述。

這很好,但有一個小小的但很重要的變化——我們使用了一個專門的函式,而不是 new Vue 例項。

//v2
const vue2App = new Vue({}) // Working with the main Vue instace
//v3
const myV3App = createApp(App).mount('#app') // Create a copy of the Vue instance

那麼,為什麼使用新的專用 createApp 函式比使用 new Vue 建構函式更好呢?

Vue 3初始化程式碼的好處

在Vue 2應用程式初始化程式碼中,我們使用了從庫中匯入的Vue物件來建立此應用程式例項以及所有其他新的應用程式例項。

使用這種方法,不可能將一些功能僅隔離到一個Vue例項中,因為Vue應用程式仍然使用從庫中匯入的同一個Vue物件。

為了演示這一點,讓我們看看下面的例子——正如你所看到的, vue2AppOnevue2AppTwo 都可以訪問一個名為 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例項,預設情況下它們不共享任何特性,即使它們是在一個檔案中建立的。

然而,如果你想在兩個例項之間共享一些功能,你可以!在下面的例子中, vue3AppOnevue3AppTwo 共享 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]
  }
})

原文:https://vueschool.io/articles/vuejs-tutorials/the-benefits-of-the-vue-3-app-initialization-code/

作者:Mikhail Kuznetsov

最近文章