Vue 3:全局 API 被取消了?

开发 前端
Vue 的 2.x 版本有很多的全局 API 和 配置,他们会在全局范围内改变 Vue 的行为。

Vue 的 2.x 版本有很多的全局 API 和 配置,他们会在全局范围内改变 Vue 的行为。

  • 比如常见的全局 API 有:Vue.component / Vue.mixin / Vue.extend / Vue.nextTick;
  • 常见的全局配置有:Vue.config.silent / Vue.config.devtools / Vue.config.productionTip

比如(官方例子),如果你想创建一个全局的组件,你会用到 Vue.component:

 

  1. Vue.component('trump-sucks', { 
  2.   data: () => ({ position: 'America president', }), 
  3.   template: `<h1>Trump is the worst ${position}</h1>`; 
  4. }); 

或者声明一个全局指令:

  1. Vue.directive('focus', { 
  2.   inserted: el => { 
  3.     console.log('聚焦!'); 
  4.     el.focus(); 
  5.   }, 
  6. }); 

这样确实比较方便,但是会造成一些问题。首先要明确的一点是,Vue 2.x 在设计上并没有 app(应用)的概念。开发者在使用 Vue 2.x 是所谓的 app 不过是一个用 new Vue()创建的 Vue 实例罢了(呵,不过如此)。由同一个 Vue 构造函数创建的 Vue 实例都会共享来自构造函数的全局配置。这将会导致:

在测试过程中,由于全局配置的存在,测试用例很容易就会被“污染”。开发者需要小心翼翼地将全局配置找一个地方存下来,在每次测试结束后将其还原,比如 Vue.config.errorHandler;一些 API 比如 Vue.use 和 Vue.mixin 甚至没有避免其影响的办法。这使得在测试中一旦涉及了插件,整个过程都会变得非常棘手。事实上,为了解决这个问题,vue-test-utils 不得不引入一个特殊的 API:createLocalVue:

  1. import { createLocalVue, mount } from '@vue/test-utls'
  2. const localVue = createLocalVue(); 
  3. localVue.use(MyPlugin); 
  4. mount(Component, { localVue }); 

还有一个避免不了的问题是,一旦页面上有多个 Vue 实例时,它们的全局配置就很自然地共享了,但在很多时候开发者并不想要这样的结果

  1. Vue.mixin({ 
  2.   mounted: () => { 
  3.     console.log('wubba lubba dub dub'); 
  4.   }, 
  5. }); 
  6.  
  7. const rick = new Vue({ el: '#rick' }); 
  8. const morty = new Vue({ el: '#morty' }); 

因此,为了规避这些问题,Vue 3 引入了应用实例的概念。

全局 API: createApp

调用 createApp 会返回一个 应用实例,没错,应用实例这个概念是 Vue 3 中新引入的。

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

应用实例会暴露一个当前全局 API 的子集。在这个重构工作中,Vue 团队秉承的经验法则是:任何会在全局范围内影响 Vue 行为的 API 都会被迁移至应用实例中去。

2.x 的全局 API 3.x 的应用实例 API 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 行为的 api 都已改造为具名导出的构建方式(named exports),就像之前尤雨溪尤大在直播里说的那样:为了支持 TreeShaking。

 

[[334669]]

挂载一个应用实例

在使用 createApp(VueInstance) 得到一个应用实例后,这个应用实例就可以用来把整个 Vue 跟实例挂载到页面上了:

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

在完成了这些改造之后,开篇我们提到的那些例子将会重写成这样:

 

  1. app.component('trump-sucks', { 
  2.   data: () => ({ position: 'America president', }), 
  3.   template: `<h1>Trump is the worst ${position}</h1>`; 
  4. }); 
  5.  
  6. app.directive('focus', { 
  7.   inserted: el => { 
  8.     console.log('聚焦!'); 
  9.     el.focus(); 
  10.   }, 
  11. }); 
  12.  
  13. // 至此,所有在 app 所包含的组件树内创建的 Vue 实例才会共享 trump-sucks 这个组件和 focus 这个指令,而 Vue 构造函数并没有被污染。 

多个应用实例的配置共享

上文提到的“不是所有开发者都想要的全局配置共享”,在 Vue 3 中可以通过工厂函数的方式实现:

  1. import { createApp } from 'vue'
  2. import CaiXuKun from './CXK.vue'
  3. import WuYiFan from './WYF.vue'
  4.  
  5. const createIdolApp = (IdolInstance) => { 
  6.  const idolApp = createApp(IdolInstance); 
  7.   idolApp.directive('sing-and-dance', { 
  8.    inserted: () => { 
  9.       console.log('I am cool!'); 
  10.     }, 
  11.   }); 
  12.  
  13. createIdolApp(CaiXuKun).mount('#caixukun'); 
  14. createIdolApp(WuYiFan).mount('#wuyifan'); 

这样就能实现多个应用实例的配置共享了:蔡徐坤和吴亦凡都有了一个叫做“唱跳”的 Vue 自定义指令。

责任编辑:未丽燕 来源: 今日头条
相关推荐

2021-07-29 12:05:18

Vue3Api前端

2020-09-19 21:15:26

Composition

2019-08-12 16:31:56

5G网络运营商

2021-12-16 08:27:54

Vue3 插件Vue应用

2020-10-20 09:30:13

Vue 3 API 数据

2020-10-20 09:51:51

Vue 3 的组合

2024-03-01 11:32:22

Vue3APIVue.js

2022-07-13 10:07:31

vue3组件监听器

2021-06-01 05:22:18

Windows操作系统微软

2020-06-12 10:12:07

苹果 iOS微信

2022-06-13 08:39:21

Vue3API

2021-05-06 07:40:56

Vue3 Vue2 组件

2024-01-04 08:38:21

Vue3API慎用

2019-08-06 08:47:18

运营商流量套餐4G服务

2009-12-18 10:30:55

Fedora Core

2009-02-02 13:01:00

雅虎裁员

2021-07-01 14:52:17

Windows 11操作系统微软

2018-11-27 09:28:41

API攻击恶意

2020-09-29 08:26:17

Vue3中新增的API

2021-12-01 08:11:44

Vue3 插件Vue应用
点赞
收藏

51CTO技术栈公众号