分类
未分类

vue3变化

vue3的变化

全局api

createApp 返回实例 替代 new Vue 使得返回实例不再共享全局配置 全局的方法也从Vue上转移到了实例上

2.x全局API 3.x实例API(app)
Vue.config app.config
Vue.config.productionTip removed
Vue.config.ignoredElements app.config.isCustomElement
Vue.component app.component
Vue.directive app.directive
Vue.mixin app.mixin
Vue.use app.use
Vue.prototype app.config.globalProperties

config.ignoredElements 就是现在 config.isCustomElement

引入此配置选项旨在支持本机自定义元素,因此重命名可以更好地传达其功能。新选项还期望一个比旧字符串/ RegExp方法具有更大灵活性的函数:

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

Vue.prototype 取而代之 config.globalProperties

在Vue 2中,Vue.prototype通常用于添加所有组件都可以访问的属性。 Vue 3中的等效项是config.globalProperties。在实例化应用程序内的组件时,将复制这些属性:

// before - Vue 2
Vue.prototype.$http = () => {}
// after - Vue 3
const app = Vue.createApp({})
app.config.globalProperties.$http = () => {}

一个经过转换的例子如下

const app = createApp(MyApp)

app.component('button-counter', {
  data: () => ({
    count: 0
  }),
  template: '<button @click="count++">Clicked {{ count }} times.</button>'
})

app.directive('focus', {
  mounted: el => el.focus()
})

// button-counter 组件与 focus指令 不会污染全局 只在当前实例
app.mount('#app')

Provide / Inject

// 在父级
app.provide('guide', 'Vue 3 Guide')

// 在任意层次的子级
export default {
  inject: {
    book: {
      from: 'guide'
    }
  },
  template: `<div>{{ book }}</div>`
}

Tree-shaking

因为内部都重写了,所以组件内部也完全是支持摇树优化的,带来的后果就是一些方法需要显式导入来使用

import { nextTick } from 'vue'

nextTick(() => {
  // something DOM-related
})
//before
import { shallowMount } from '@vue/test-utils'
import { MyComponent } from './MyComponent.vue'

test('an async feature', async () => {
    const wrapper = shallowMount(MyComponent)

    // execute some DOM-related tasks

    await wrapper.vm.$nextTick()

    // run your assertions
})
//after
import { shallowMount } from '@vue/test-utils'
import { MyComponent } from './MyComponent.vue'
import { nextTick } from 'vue'

test('an async feature', async () => {
    const wrapper = shallowMount(MyComponent)

    // execute some DOM-related tasks

    await nextTick()

    // run your assertions
})

####受影响的API

2.x全局API 3.x用法
Vue.nextTick 拆分
Vue.observable 替换为 Vue.reactive
Vue.version 拆分
Vue.compile 仅完整版本
Vue.set 仅在兼容版本中
Vue.delete 仅在兼容版本中

参考链接

$attrs的变化

在vue2中,classstyle会被直接设置到组件的根元素并且不会出现在 $attrs中, 当inheritAttrs:false的时候

<template>
  <label>
    <input type="text" v-bind="$attrs" />
  </label>
</template>
<script>
export default {
  inheritAttrs: false
}
</script>

当这样使用的时候

<my-component id="my-id" class="my-class"></my-component>

vue2将生成以下html

<label class="my-class">
    <input type="text" id="my-id" />
</label>

vue3中$attr包含所有属性包括class与style vue3将生成以下html

<label>
    <input type="text" id="my-id" class="my-class" />
</label>

$listeners 在vue3也被移除,现在是$attrs的一部分

自定义指令的生命周期变化

简要总结:

  • API 已重命名,以便更好地与组件生命周期保持一致
  • 自定义指令将由子组件通过 v-bind="$attrs"

对比

2.x 3.x
bind beforeMount
inserted mounted
beforeUpdate
update 已经移除 改用 updated
componentUpdated updated
beforeUnmount
unbind unmounted

###生命周期变化 TODO

###scopedSlots正式弃用 v-slot 指令自 Vue 2.6.0 起被引入,提供更好的支持 slot 和 slot-scope attribute 的 API 替代方案。 v-slot 完整的由来参见这份 RFC 。 在接下来所有的 2.x 版本中 slot slot-scopeattribute 仍会被支持, 但不会出现在 Vue 3 中。 结合具名插槽要这样写

<span>
  <slot v-bind:user="user">
    {{ user.lastName }}
  </slot>
</span>

异步组件需要显式定义

Mixin合并行为变更

当来自组件的 data() 及其 mixin 或 extends 基类被合并时,现在将浅层次执行合并:

const Mixin = {
  data() {
    return {
      user: {
        name: 'Jack',
        id: 1
      }
    }
  }
}
const CompA = {
  mixins: [Mixin],
  data() {
    return {
      user: {
        id: 2
      }
    }
  }
}

vue2中结果是

{
  user: {
    id: 2,
    name: 'Jack'
  }
}

vue3中结果是

{
  user: {
    id: 2
  }
}
分类
未分类

下一阶段预告

接下来半年内要做的事情

1.重构一个v-viewer-vue3版本的

2.开源一个可配置页面的前后端版本

欢迎加群催更 交流技术 秋秋群号:768901972