其他
Vue 3.5“天元突破红莲螺岩”正式发布
这个小版本不包含任何破坏性变更,同时包括了内部改进和实用的新功能。
我们将在这篇博文中介绍一些亮点 - 如需完整的变更和新功能列表,请参阅 GitHub 上的完整更新日志。
https://github.com/vuejs/core/blob/main/CHANGELOG.md
响应式系统优化
在 3.5 中,Vue 的响应式系统经历了又一次重大重构,实现了更好的性能和显著减少了内存占用(-56%),且没有行为变化。
这次重构还解决了 SSR 过程中由于悬挂的计算属性导致的过时计算值和内存问题。
此外,3.5 还优化了对大型、深度响应式数组的响应式追踪,在某些情况下使此类操作的速度提高了多达 10 倍。
<script setup>
中从defineProps
调用解构的变量现在是响应式的。const props = withDefaults(
defineProps<{
count?: number
msg?: string
}>(),
{
count: 0,
msg: 'hello'
}
)
After
count?: number
message?: string
}>()
count
)时,编译器会自动将其编译为props.count
,因此它们在访问时会被追踪。props.count
类似,如果要观察解构的 prop 变量或将其传递给组合式函数并保持响应性,需要将其包装在一个 getter 中:watch(count /* ... */)
// ^ results in compile-time error
watch(() => count /* ... */)
// ^ wrap in a getter, works as expected
// composables should normalize the input with `toValue()`
useDynamicCount(() => count)
@vue/language-tools
2.1 版本已经发布了一个可选设置,可以为它们启用内联提示:详情:
使用方法和注意事项请参阅文档。
有关此功能的历史和设计理念,请参阅 RFC#502。
https://vuejs.org/guide/components/props.html#reactive-props-destructure
https://github.com/vuejs/rfcs/discussions/502
SSR 改进
3.5 为服务器端渲染(SSR)带来了一些期待已久的改进。
Lazy Hydration(懒加载水合)
异步组件现在可以通过defineAsyncComponent()
API 的hydrate
选项来控制何时进行水合。
例如,只在组件变为可见时才进行水合:
const AsyncComp = defineAsyncComponent({
loader: () => import('./Comp.vue'),
hydrate: hydrateOnVisible()
})
核心 API 故意设计得比较底层,Nuxt 团队已经在这个功能之上构建了更高级的语法糖。
useId()
useId()
是一个可以用来生成应用内唯一 ID 的 API,这些 ID 保证在服务器和客户端渲染之间保持稳定。
它们可以用于生成表单元素和无障碍属性的 ID,并且可以在 SSR 应用中使用而不会导致水合不匹配:
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
data-allow-mismatch
属性来抑制由此产生的水合不匹配警告:<span data-allow-mismatch>{{ data.toLocaleString() }}</span>
text
、children
、class
、style
和 attribute
。自定义元素改进
3.5 修复了许多与defineCustomElement()
API 相关的长期存在的问题,并为使用 Vue 创建自定义元素添加了一些新功能:
通过 configureApp
选项支持自定义元素的应用配置。添加 useHost()
、useShadowRoot()
和this.$host
API,用于访问自定义元素的宿主元素和影子根。通过传递 shadowRoot: false
支持挂载不带影子 DOM 的自定义元素。支持提供 nonce
选项,该选项将附加到自定义元素注入的<style>
标签上。
这些新的仅用于自定义元素的选项可以通过第二个参数传递给defineCustomElement
:
import MyElement from './MyElement.ce.vue'
defineCustomElements(MyElement, {
shadowRoot: false,
nonce: 'xxx',
configureApp(app) {
app.config.errorHandler = ...
}
})
其他值得关注的特性
useTemplateRef()
useTemplateRef()
API 获取模板引用的新方法: import { useTemplateRef } from 'vue'
const inputRef = useTemplateRef('input')
</script>
<template>
<input ref="input">
</template>
ref
属性匹配。旧方法要求ref
属性可以被编译器分析,因此仅限于静态ref
属性。useTemplateRef()
通过运行时字符串 ID 匹配 ref,因此支持动态 ref 绑定到变化的 ID。@vue/language-tools
2.1 也为新语法实现了特殊支持,因此在使用useTemplateRef()
时,根据 ref 属性存在与否会有自动完成和警告出现:Deferred Teleport(延迟传送门)
<Teleport>
组件的一个已知限制是,其目标元素必须在传送门组件挂载时存在。这阻止了用户将内容传送到 Vue 在传送门之后渲染的其他元素。<Teleport>
<Teleport defer to="#container">...</Teleport>
<div id="container"></div>
defer
属性,因为默认行为需要向后兼容。