不完全Vue3迁移指南

2,482 阅读2分钟

「这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战」。

Vue3已经出来一段时间了,相信大家都知道了Vue3做了一些优化,比如改用Proxy劫持数据,弥补了Vue2 使用defineProperty 带来的一些问题(比如无法感知到对象新增属性的改动,无法监听数组的length属性等),在开始着手迁移自己的项目前,要先了解从Vue2项目迁移到Vue3有哪些api、语法等破坏性即不兼容Vue2的地方,然后根据现有项目的依赖制定迁移计划。

破坏性改动

  • 因为考虑到tree-shaking,全局API需要引入

    // Vue2
    this.$nextTick(() => {})
    
    // Vue3
    import { nextTick } from 'vue'
    
    setup() {
     ...nextTick(() => {})
    }
    
  • Ref

    v-for 中的ref绑定需定义一个数组+一个新增数组的函数,而不是直接创建一个数组,使得操作更灵活;

    <div v-for="item in list" :ref="setItemRef"></div>
    
    ...
    data() {
        return {
          itemRefs: []
        }
      },
      methods: {
        setItemRef(el) {
          if (el) {
            this.itemRefs.push(el)
          }
        }
      },
    
  • .sync -> v-model

    子组件需要修改prop时,Vue2是需要title.sync 修饰符+在子组件内emit('update:title', val), Vue3 可直接用v-model:title;

    <input v-model="inputVal">  //Vue2 或者v-model:modelValue = "inputVal"
    
    <input :value="inputVal" @update:value="inputVal = $event"/>  // Vue3
    
  • v-for > v-if => v-if > v-for

    Vue3 中同时绑定v-for跟v-if在同一个组件上时,v-for的优先级更高,Vue3则相反;

  • v-bind 有顺序的区别了,绑定对象时属性会被靠后的覆盖

  • 异步组件需要使用 defineAsyncComponent 方法去创建

  • 组件事件需要写在 emits 中

    类似props,接受一个对象。因为移除了 .native 修饰符,如果没有在中在emits中声明的emits事件会被写入组件的emits事件会被写入组件的attrs, 被挂到组件的根节点,可能会触发两次;

  • destroyted => unmounted; beforeDestory => beforeUnmount

  • mixin中的 data 合并改为浅比较

    之前的data如果为嵌套的对象,那么对象中的属性也会被合并,Vue3中直接用组件中的data里面的对象去覆盖mixin data里面的同名对象。

新增

template,portal等功能。

  • template

    Vue2 可通过安装插件vue-fragment 实现React中Fragment的效果,Vue3中默认支持;

  • Teleport

    类似React中的Portal;

  • $attrs 新增了 class 跟 style 属性。

废除

  • Filters

    可用计算属性替代;

  • :event.native 修饰符不支持了

    合理使用emits替代;

  • $children 属性

    可用$refs 替代。

以上是笔者比较关心或者觉得重要的改动,未介绍到的地方,请参考其他文档、文章。

参考

迁移介绍