Vue3 迁移指南

概述

这是本人对组织版项目 Vue3 重构过程的相关总结。

官方迁移指南清晰地列出了 Vue2 到 Vue3 迁移需要注意的 breaking changes 和相关变动。其中有部分细节在实际重构时需要注意,下面展开讲讲。

可以提前开始做的

项目仍处于 Vue 2.x 时即可开始的部分重构内容,可以使重构周期的工作量曲线更加平滑。

大致流程

潜在坑点

组件 v-model 变化

问题:迁移时不能直接全局替换,比如 Option 组件 props 依旧是 value 属性,input 原生标签依旧是 value/@input

解决:需要全局搜索 value/@input 后仔细核对替换。

<XXX v-model="form"></XXX>

<!-- Vue 2 等价于 -->
<XXX :value="form" @input="form = $event"></XXX>

<!-- Vue 3 等价于 -->
<XXX :model-value="form" @update:modelValue="form = $event"></XXX>

组件 class 继承问题

问题:template 内支持了多个子节点/Teleport 功能,有潜在的样式继承问题。

解决:

  1. vite 添加配置
vue({
      template: {
        compilerOptions: {
          whitespace: 'preserve',
          comments: false, // template 内忽略注释节点
        },
      },
    }),

  1. 注意 heywhale-ui Drawer/Model/Dropdown 如果样式有问题的话可以把 class 改为 class-name。
<Drawer class="xxx-drawer"></Drawer>
<!-- class 有问题的话换成 class-name -->
<Drawer class-name="xxx-drawer"></Drawer>

HTML Element attribute 行为变化

https://v3-migration.vuejs.org/zh/breaking-changes/attribute-coercion.html

问题:原生 html 的非官方 attribute 属性值为 false 时,在 vue 3 里不会被移除。

解决:避免对原生 html 的非官方 attribute 设置 false 值。

<!-- Vue 3 会解析为 <a disabled="false">链接</a> 其实还是 disabled 了... -->
<a :disabled="!!isDisabled">链接</a>

<!-- Vue 3 需要改变写法 -->
<a :disabled="isDisabled ? true : null">链接</a>
<!-- 或者 a 标签暂时先替换为 Link 组件 -->
<Link :disabled="!!isDisabled">链接</Link>

$ 开头的响应式属性失效

问题:Vue 3 为了防止内部属性冲突,直接不再对$开头的变量进行响应式代理,甚至直接读不到值。

解决:重命名,避免$ _开头的响应式属性命名。

data() {
    return {
        validName: 'validName',

        // this.$instance 读不到,始终为 undefined,需要更换名称为 instance
        $instance: new instance()
    }
}

部分三方依赖库实例响应式问题

问题:选项式写法中,给三方依赖实例响应式赋值时,会导致依赖自身功能实现出问题。

解决:用 markRaw 标记为不需要响应式代理。

import { markRaw } from 'vue';

data() {
    return {
        codemirror: null
    }
},
mounted() {
    this.codemirror = markRaw(CodeMirror.fromTextArea(this.$refs.textarea, cmOptions))
}

extends 不会继承 setup 函数

问题:父组件 extends 子组件的时候,如果子组件里有 setup 函数,父组件不会继承。

解决:不要混用组合式和选项式写法,以后尽量用组合式写法吧!

heywhale-ui

<!-- Page 组件的 current props 需要替换为 v-model -->
<Page :current=""></Page>

<Page v-model=""></Page>

重构 todo list 快速核对