3.5 新特性
❗ 没有包含所有更新,只记录后续开发可能会用得到的改进
水合改进
useId
新引入一个 api: useId
, 生成每个应用唯一的 ID, 确保在服务端和客户端渲染之间保持稳定:
vue
<script setup>
import { useId } from "vue";
const id = useId();
</script>
<template>
<form>
<label :for="id">Name:</label>
<input :id="id" type="text" />
</form>
</template>
data-allow-mismatch
在某些情况下,客户端的值和服务端的值会不可避免的不同(如日期),可以使用新 api: data-allow-mismatch
来抑制水合不匹配的警告:
html
<span data-allow-mismatch>{{ data.toLocaleString() }}</span>
响应式解构
vue
<script setup>
const props = withDefaults(
defineProps<{
count?: number
msg?: string
}>(),
{
count: 0,
msg: 'hello'
}
)
</script>
vue
<script setup>
const { count = 0, msg = 'hello' } = defineProps<{
count?: number
message?: string
}>()
</script>
结构后得变量会自动编译为:props.var
useTemplateRef()
增加了一种新的模板引用方式:useTemplateRef()
它返回一个浅层 ref,其值将与模板中的具有匹配 ref attribute 的元素或组件同步
新模板引用方式主要改进了 v-for 循环中的行为:
- 传统 ref 在 v-for 中容易出错和内存泄露;
- useTemplateRef 完美地解决了上述问题。它会自动响应列表的变化,其对应的 ref 值总会指向“当前”最新的、正确的元素:
- 当列表项被移除时,对应的引用会自动变为 null;
- 当列表项被添加时,会生成新的引用指向新元素;
- 你无需手动维护一个引用数组,它本身是响应式的。
示例(ref):
vue
<template>
<div v-for="item in list" :key="item.id" :ref="setItemRef">
{{ item.name }}
</div>
</template>
<script setup>
import { ref, onBeforeUpdate } from 'vue';
const list = ref([...]); // 一些数据
const itemRefs = ref([]); // 用于存放引用的数组
// 设置引用的函数
const setItemRef = (el) => {
if (el) {
itemRefs.value.push(el);
}
};
// 重要:在更新前清空数组,否则会不断累积旧的引用
onBeforeUpdate(() => {
itemRefs.value = [];
});
</script>
示例(useTemplateRef):
vue
<template>
<div v-for="item in list" :key="item.id" :ref="itemRefs.set">
{{ item.name }}
</div>
</template>
<script setup>
import { useTemplateRef } from 'vue';
const list = ref([...]); // 一些数据
// 创建一个模板引用列表
const itemRefs = useTemplateRef('itemRefsKey'); // 需要提供一个唯一的 key
// 注意:itemRefs 本身是一个 ref,但其值是一个对象(或 null)
// 在 onMounted 后,你可以通过 itemRefs.value 来访问所有当前元素的引用
// 例如:itemRefs.value[0] 指向第一个元素
</script>
Deferred Teleport
使用 teleport
传送时,引入 defer
属性,它会在当前渲染周期之后进行挂载
vue
<template>
<Teleport defer target="#container">...</Teleport>
<div id="container"></div>
</template>
onWatcherCleanup()
引入一个新 api: onWatcherCleanup
, 用于在 watch
中注册清理回调:
vue
<script setup>
import { watch, onWatcherCleanup } from "vue";
watch(id, (newId) => {
const controller = new AbortController();
fetch(`/api/${newId}`, { signal: controller.signal }).then(() => {
// callback logic
});
onWatcherCleanup(() => {
// abort stale request
controller.abort();
});
});
</script>