Vue 3.0 全局API

2021-07-16 11:45 更新

Vue 2.x 有許多全局 API 和配置,這些 API 和配置可以全局改變 Vue 的行為。例如,要?jiǎng)?chuàng)建全局組件,可以使用 Vue.component 這樣的 API:

  1. Vue.component('button-counter', {
  2. data: () => ({
  3. count: 0
  4. }),
  5. template: '<button @click="count++">Clicked {{ count }} times.</button>'
  6. })

類(lèi)似地,使用全局指令的聲明方式如下:

  1. Vue.directive('focus', {
  2. inserted: el => el.focus()
  3. })

雖然這種聲明方式很方便,但它也會(huì)導(dǎo)致一些問(wèn)題。從技術(shù)上講,Vue 2 沒(méi)有“app”的概念,我們定義的應(yīng)用只是通過(guò) new Vue() 創(chuàng)建的根 Vue 實(shí)例。從同一個(gè) Vue 構(gòu)造函數(shù)創(chuàng)建的每個(gè)根實(shí)例共享相同的全局配置,因此:

  • 在測(cè)試期間,全局配置很容易意外地污染其他測(cè)試用例。用戶(hù)需要仔細(xì)存儲(chǔ)原始全局配置,并在每次測(cè)試后恢復(fù) (例如重置 Vue.config.errorHandler)。有些 API 像 Vue.use 以及 Vue.mixin 甚至連恢復(fù)效果的方法都沒(méi)有,這使得涉及插件的測(cè)試特別棘手。實(shí)際上,vue-test-utils 必須實(shí)現(xiàn)一個(gè)特殊的 API createLocalVue 來(lái)處理此問(wèn)題:

  1. import { createLocalVue, mount } from '@vue/test-utils'
  2. // 建擴(kuò)展的 `Vue` 構(gòu)造函數(shù)
  3. const localVue = createLocalVue()
  4. // 在 “l(fā)ocal” Vue構(gòu)造函數(shù)上 “全局” 安裝插件
  5. localVue.use(MyPlugin)
  6. // 通過(guò) `localVue` 來(lái)掛載選項(xiàng)
  7. mount(Component, { localVue })

  • 全局配置使得在同一頁(yè)面上的多個(gè)“app”之間共享同一個(gè) Vue 副本非常困難,但全局配置不同。

  1. // 這會(huì)影響兩個(gè)根實(shí)例
  2. Vue.mixin({
  3. /* ... */
  4. })
  5. const app1 = new Vue({ el: '#app-1' })
  6. const app2 = new Vue({ el: '#app-2' })

為了避免這些問(wèn)題,在 Vue 3 中我們引入...

#一個(gè)新的全局 API:createApp

調(diào)用 createApp 返回一個(gè)應(yīng)用實(shí)例,這是 Vue 3 中的新概念:

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

應(yīng)用實(shí)例暴露當(dāng)前全局 API 的子集,經(jīng)驗(yàn)法則是,任何全局改變 Vue 行為的 API 現(xiàn)在都會(huì)移動(dòng)到應(yīng)用實(shí)例上,以下是當(dāng)前全局 API 及其相應(yīng)實(shí)例 API 的表:

2.x 全局 API 3.x 實(shí)例 API (app)
Vue.config app.config
Vue.config.productionTip removed (見(jiàn)下方)
Vue.config.ignoredElements app.config.isCustomElement (見(jiàn)下方)
Vue.component app.component
Vue.directive app.directive
Vue.mixin app.mixin
Vue.use app.use (見(jiàn)下方)

所有其他不全局改變行為的全局 API 現(xiàn)在被命名為 exports,文檔見(jiàn)全局 API Treeshaking。

#config.productionTip 移除

在 Vue 3.x 中,“使用生產(chǎn)版本”提示僅在使用“dev + full build”(包含運(yùn)行時(shí)編譯器并有警告的構(gòu)建) 時(shí)才會(huì)顯示。

對(duì)于 ES 模塊構(gòu)建,由于它們是與 bundler 一起使用的,而且在大多數(shù)情況下,CLI 或樣板已經(jīng)正確地配置了生產(chǎn)環(huán)境,所以本技巧將不再出現(xiàn)。

#config.ignoredElements 替換為 config.isCustomElement

引入此配置選項(xiàng)的目的是支持原生自定義元素,因此重命名可以更好地傳達(dá)它的功能,新選項(xiàng)還需要一個(gè)比舊的 string/RegExp 方法提供更多靈活性的函數(shù):

  1. // before
  2. Vue.config.ignoredElements = ['my-el', /^ion-/]
  3. // after
  4. const app = Vue.createApp({})
  5. app.config.isCustomElement = tag => tag.startsWith('ion-')

重要

在 3.0 中,元素是否是組件的檢查已轉(zhuǎn)移到模板編譯階段,因此只有在使用運(yùn)行時(shí)編譯器時(shí)才考慮此配置選項(xiàng)。如果你使用的是 runtime-only 版本 isCustomElement 必須通過(guò) @vue/compiler-dom 在構(gòu)建步驟替換——比如,通過(guò) compilerOptions option in vue-loader

  • 如果 config.isCustomElement 當(dāng)使用僅運(yùn)行時(shí)構(gòu)建時(shí)時(shí),將發(fā)出警告,指示用戶(hù)在生成設(shè)置中傳遞該選項(xiàng);
  • 這將是 Vue CLI 配置中新的頂層選項(xiàng)。

#插件使用者須知

插件開(kāi)發(fā)者通常使用 Vue.use。例如,官方的 vue-router 插件是如何在瀏覽器環(huán)境中自行安裝的:

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

由于 use 全局 API 在 Vue 3 中不再使用,此方法將停止工作并停止調(diào)用 Vue.use() 現(xiàn)在將觸發(fā)警告,于是,開(kāi)發(fā)者必須在應(yīng)用程序?qū)嵗巷@式指定使用此插件:

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

#掛載 App 實(shí)例

使用 createApp(/* options */) 初始化后,應(yīng)用實(shí)例 app 可用于掛載具有 app.mount(domTarget)

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

經(jīng)過(guò)所有這些更改,我們?cè)谥改祥_(kāi)頭的組件和指令將被改寫(xiě)為如下內(nèi)容:

  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. // 現(xiàn)在所有應(yīng)用實(shí)例都掛載了,與其組件樹(shù)一起,將具有相同的 “button-counter” 組件 和 “focus” 指令不污染全局環(huán)境
  12. app.mount('#app')

#提供/注入 (Provide / Inject)

與在 2.x 根實(shí)例中使用 provide 選項(xiàng)類(lèi)似,Vue 3 應(yīng)用實(shí)例還可以提供可由應(yīng)用內(nèi)的任何組件注入的依賴(lài)項(xiàng):

  1. // 在入口
  2. app.provide('guide', 'Vue 3 Guide')
  3. // 在子組件
  4. export default {
  5. inject: {
  6. book: {
  7. from: 'guide'
  8. }
  9. },
  10. template: `<div>{{ book }}</div>`
  11. }

#在應(yīng)用之間共享配置

在應(yīng)用之間共享配置 (如組件或指令) 的一種方法是創(chuàng)建工廠(chǎng)功能,如下所示:

  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')

現(xiàn)在,F(xiàn)oo 和 Bar 實(shí)例及其后代中都可以使用 focus 指令。

以上內(nèi)容是否對(duì)您有幫助:
在線(xiàn)筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)