第 85 期 - Vue3.5 版本新特性全解读
logoFRONTALK AI/1月17日 16:31/阅读原文

摘要

文章对 Vue3.5 版本的新特性做了全面解读,包括响应式相关改进、SSR 服务端渲染的更新、组件相关改进等,这些新特性在特定场景下有很大用处,值得开发者升级。

一、响应式相关改进

响应式相关改进包含多个方面内容。

1. 重构响应式

这是 Vue 内部优化,普通开发者无感。其通过版本计数和双向链表数据结构(灵感来源于 Preact signals)使内存占用减少 56%。作者后续还会出响应式相关源码文章。

2. 响应式 props 支持解构

在 3.5 版本之前,在 js 中访问 prop 必须写props.name,否则name会丢失响应式。3.5 版本有了响应式 props 解构后,可以直接解构出name使用,例如:

<script setup lang="ts">
const { name } = defineProps({
  name: String,
});
console.log(name);
</script>

编译后简化代码如下:

setup(__props) {
  console.log(__props.name);
  const __returned__ = {};
  return __returned__;
}

这样name就不会丢失响应式。

3. 新增 onEffectCleanup 函数

在组件卸载之前或者下一次watchEffect回调执行之前会自动调用onEffectCleanup函数。例如:

import { watchEffect, ref } from "vue";
import { onEffectCleanup } from "@vue/reactivity";
const flag = ref(true);
watchEffect(() => {
  if (flag.value) {
    const timer = setInterval(() => {
      // 做一些事情
      console.log("do something");
    }, 200);
    onEffectCleanup(() => {
      clearInterval(timer);
    });
  }
});

有了这个函数就不需要在beforeUnmount钩子函数中清理timer。不过要注意这个函数目前没有在vue包中暴露,需要从@vue/reactivity包中导入。

4. 新增 base watch 函数

之前watch函数和 Vue 组件及生命周期深度绑定,代码在runtime - core模块。但在一些场景(如小程序vuemini)只想使用vue的响应式功能(reactivity模块)时,3.5 版本重构了base watch函数,它在reactivity模块,和 Vue 组件无关系。这对普通开发者影响不大,但对下游项目(如vuemini)有益。

5. 新增 onWatcherCleanup 函数

onEffectCleanup函数类似,在组件卸载之前或者下一次watch回调执行之前会自动调用onWatcherCleanup函数。例如:

import { watch, ref, onWatcherCleanup } from "vue";
watch(flag, () => {
  const timer = setInterval(() => {
    // 做一些事情
    console.log("do something");
  }, 200);
  onWatcherCleanup(() => {
    console.log("清理定时器");
    clearInterval(timer);
  });
});

这里可以直接从vue中导入onWatcherCleanup函数。

6. 新增 pause 和 resume 方法

在一些场景中想暂停watch或者watchEffect中的回调,满足业务条件后再恢复执行就可以使用这两个方法。例如watchEffect的例子:

<template>
  <button @click="count ++">count ++</button>
  <button @click="runner2.pause()">暂停</button>
  <button @click="runner2.resume()">恢复</button>
</template>
<script setup lang="ts">
import { watchEffect } from "vue";
const count = ref(0);
const runner2 = watchEffect(() => {
  if (count.value > 0) {
    console.log(count.value);
  }
});
</script>

点击count ++按钮理论上每次都会执行watchEffect回调,点击暂停按钮执行pause方法暂停后回调就不执行了,点击恢复按钮执行resume方法恢复后回调重新执行。watch也可以执行这两个方法。

7. watch 的 deep 选项支持传入数字

以前deep选项的值只能是falsetrue,表示是否深度监听对象。3.5 版本deep选项支持传入数字,表示监控对象的深度。例如:

const obj1 = ref({
  a: {
    b: 1,
    c: {
      d: 2,
      e: {
        f: 3,
      },
    },
  },
});
watch(
  obj1,
  () => {
    console.log("监听到 obj1 变化");
  },
  {
    deep: 3,
  }
);
function changeDeep3Obj() {
  obj1.value.a.c.d = 20;
}
function changeDeep4Obj() {
  obj1.value.a.c.e.f = 30;
}

deep选项值为 3 时,修改对象第 3 层的d属性能触发watch回调,修改第 4 层的f属性不能触发。

二、SSR 服务端渲染

1. 新增 useId 函数

在 SSR 服务端渲染中,如果像下面这样生成随机数作为id会有警告:

<template>
  <label :htmlFor="id">Do you like Vue3.5?</label>
  <input type="checkbox" name="vue3.5" :id="id" />
</template>
<script setup lang="ts">
const id = Math.random();
</script>

因为服务端和客户端都会执行Math.random()生成不同的iduseId函数可解决此问题,它也可用于客户端渲染中需要唯一键但服务端未提供的场景。

2. Lazy Hydration 懒加载水合

异步组件现在可通过defineAsyncComponent()API 的hydrate选项控制何时水合,作者认为普通开发者用不上所以未细讲。

3. data - allow - mismatch

在 SSR 中,服务端和客户端生成的html可能不一致(如渲染当前时间)会有警告,可使用data - allow - mismatch属性干掉警告,例如:

<template>
  <div data - allow - mismatch>当前时间是:{{ new Date() }}</div>
</template>

三、组件相关改进

1. Teleport 组件新增 defer 延迟属性

Teleport组件可将children内容传送到指定位置。之前有个限制,不能将目标元素放在Teleport组件后面。3.5 版本新增defer延迟属性解决了此问题。例如:

<Teleport defer to="# target">被传送的内容</Teleport>
<div id="target"></div>

defer延迟属性等一轮渲染周期结束后再渲染Teleport组件,所以就算目标元素在Teleport组件后面也能正常传送内容。

2. useTemplateRef 函数

vue3中使用ref访问 DOM 和子组件存在一些问题,比如定义的ref变量是响应式数据还是 DOM 元素容易混淆,templateref属性值是字符串却能和script中同名变量绑定等。3.5 版本的useTemplateRef函数可解决这些问题。例如:

<input type="text" ref="inputRef" />
const inputEl = useTemplateRef<HTMLInputElement>("inputRef");

使用useTemplateRef函数后返回的ref变量指向 DOM 元素输入框,比之前的体验好很多。

四、总结

对于开发者来说,Vue3.5 版本新增了很多有趣功能,如onEffectCleanup函数、onWatcherCleanup函数、pauseresume方法、watchdeep选项支持传入数字、useId函数、Teleport组件新增defer延迟属性、useTemplateRef函数等。这些功能在特殊场景下很有用,作者认为值得将 Vue 升级到 3.5 版本。

 

扩展阅读

Made by 捣鼓键盘的小麦 / © 2025 Front Talk 版权所有