官网更新内容地址:https://blog.vuejs.org/posts/vue-3-3
更新日期:2023.12.28
- Volar / vue-tsc@^1.8.27 (required)
- @vitejs/plugin-vue@^5.0.0 (if using Vite)
- nuxt@^3.9.0 (if using Nuxt)
- vue-loader@^17.4.0 (if using webpack or vue-cli)
性能提升:
在性能方面,Vue 3.4 做出了重大的内部改进。其中最引人注目的是模板解析器的全新重写。与之前基于正则表达式的解析器相比,新的解析器使用基于状态机的标记化技术,它通过单次遍历整个模板字符串来解析模板,显著提高了解析速度,模板解析器速度提高了2倍。无论是小型还是大型的 Vue 模板,新解析器都能保持两倍的性能提升,同时确保了向后兼容性。
另一个值得关注的升级是对响应系统的重构。在旧版本中,即使计算属性的结果未发生变化,每次依赖项更新,观察者也会被触发。而在 Vue 3.4 中,优化后的系统确保只有在计算结果实际变化时,相关的效果才会被触发,从而减少了组件的不必要渲染,提升了整体的性能。
3.4 还对响应式系统进行了实质性的重构,目的是提高计算属性的重新计算效率。
为了说明正在改进的内容,让我们考虑以下方案:
const count = ref(0)
const isEven = computed(() => count.value % 2 === 0)
watchEffect(() => console.log(isEven.value)) // logs true
count.value = 2 // logs true again
在 3.4 之前,即使计算结果保持不变,每次 count.value 都将触发 watchEffect 的回调。在 3.4 之后的优化中,回调现在仅在计算结果实际更改时触发。
此外,在 3.4 中:
多个计算的 dep 更改仅触发一次同步效果。
数组的 shift, unshift, splice 方法仅触发一次同步效果。
除了基准测试中显示的收益外,这应该会减少许多场景中不必要的组件重新渲染,同时保持完全的向后兼容性。
API 改进与新特性:
defineModel API 的稳定化及功能
在之前的版本中作为实验性功能引入的 defineModel,在 Vue 3.4 中正式成为稳定特性。这个 API 主要用于简化支持 v-model 的组件实现,并在最新版本中增加了对 v-model 修饰符的支持。例如,你可以使用 defineModel 来创建一个响应式的输入组件,这个组件能够处理数字类型的 v-model:
官方说明:https://cn.vuejs.org/api/sfc-script-setup.html#definemodel
defineModel 是一个新的
// 声明 “count” prop,由父组件通过 v-model:count 使用
const count = defineModel(“count”)
// 或者:声明带选项的 “count” prop
const count = defineModel(“count”, { type: Number, default: 0 })
function inc() {
// 在被修改时,触发 “update:count” 事件
count.value++
}
实现v-model组件数据绑定:
v-bind 的同名简写功能
Vue 3.4 引入了 v-bind 的同名简写功能,使得开发者在模板中绑定属性时可以省略重复的变量名。当属性名和绑定的变量名相同时,可以直接使用属性名,从而使模板更加简洁。例如,对于一个需要绑定多个属性的组件,传统的写法和新的简写方法对比如下:
watch 新增 once 选项
Vue 3.4 为 watch 函数增加了 once 选项,这使得观察者在第一次检测到变化时就会停止,非常适用于只需响应一次数据变化的场景。这个新选项提供了一种简洁的方式来防止重复触发。例如,你可以使用 once 来观察一个状态值的变化,并在它第一次改变时执行某个操作:
watch(someRef, () => {
// 这个函数只会在 someRef 第一次变化时执行
}, { once: true});
TypeScript 改进:
对于使用 TypeScript 的开发者来说,Vue 3.4 带来了多项类型系统的改进。Vue 团队清理了类型定义,使得类型更加严格和清晰,这对于整个生态系统的库都大有裨益。例如,在注册全局指令时,现在可以为 app.directive 方法提供适当的类型注解,从而获得更好的类型检查:
app.directive<HTMLElement, string>(‘focus’, {
mounted(el, binding) {
el.focus();
console.log(binding.value); // binding.value 类型为 string
}
});
这样的改进为开发者提供了更精确的类型支持,减少了类型相关的错误,使得代码更加健壮和可维护。
其他
- 全局 JSX 命名空间
从 3.4 开始,Vue 默认不再注册全局 JSX 命名空间。这是避免与 React 发生全局命名空间冲突所必需的,以便两个库的 TSX 可以共存于同一个项目中。这应该不会影响使用最新版本的 Volar 的 SFC 的用户。
如果您使用的是 TSX,则有两种选择: - 在升级到 3.4 之前,在tsconfig.json 中将 jsxImportSource 显式设置为 ‘vue’。您还可以通过在文件顶部添加 /* @jsxImportSource vue */ 注释来选择加入每个文件。
- 如果您的代码依赖于全局 JSX 命名空间的存在,例如使用 JSX.Element 类型等,则可以通过显式引用 vue/jsx 来保留 3.4 之前的确切全局行为,这将注册全局 JSX 命名空间。
- 其他已删除的功能
- 反应性转换在 3.3 版本中被标记为已弃用,现在在 3.4 版本中删除。由于该功能是实验性的,因此此更改不需要 在major 版本。希望继续使用该功能的用户可以通过 Vue Macros 插件进行。
- app.config.unwrapInjectedRef 已被删除。它在 3.3 中已弃用并默认启用。在 3.4 中,无法再禁用此行为。
- @vnodeXXX 模板中的事件侦听器现在是编译器错误,而不是弃用警告。请改用 @vue:XXX 侦听器。
- v-is 指令已被删除。它在 3.3 中已弃用。请改用带 vue: 前缀的 is 属性。
升级指南安装使用:
pnpm install vue@^3.4
pnpm install @vitejs/plugin-vue@^5.0.0
pnpm install vue-tsc@^1.8.27
// 如果使用了volar则需要升级
pnpm install volar@^1.8.27
查看package.json中的版本:
“vue”: “^3.4”,
“vue-tsc”: “^1.8.27”
“@vitejs/plugin-vue”: “^5.0.0”,
对于v-bind新语法,可以使用,但是会有eslint、vue、ts报错,注释掉可能会有一些其他的影响。暂时还是老老实实写旧语法吧
‘vue/valid-v-bind’: ‘off’, // 关闭v-bind新语法报错