响应式 props 解构
vue3.5 中 props 正式支持解构了,并添加了响应式跟踪
设置默认值
使用 javascript 原生的默认值语法声明 props 默认值
以前
const props = withdefaults( defineprops<{ count?: number msg?: string }>(), { count: 0, msg: 'hello' } )
现在
const { count = 0, msg = 'hello' } = defineprops<{ count?: number message?: string }>()
响应式解构
当在同一个 <script setup> 代码块中访问由 defineprops 解构的变量时,vue 编译器会自动在前面添加 props
以前
const { foo } = defineprops(['foo']) watcheffect(() => { // 在 3.5 之前只运行一次 console.log(foo) })
现在
const { foo } = defineprops(['foo']) watcheffect(() => { // 在 3.5 中在 "foo" prop 变化时重新执行 console.log(foo) // `foo` 由编译器转换为 `props.foo`,以上等同于 `console.log(props.foo)` })
与之类似,监听解构的 prop 变量 或 将其传递到可组合项中同时保留响应性 时需要将其包装在 getter 中
以前
const { foo } = defineprops(['foo']) watch(foo, /* ... */)
现在:
// watch(foo, /* ... */) 等价于 watch(props.foo, ...),我们给 watch 传递的是一个值而不是响应式数据源 watch(() => foo, /* ... */) // 传递解构的 prop 到外部函数中并保持响应性 usecomposable(() => foo)
监听(watch / watcheffect) 相关
watch 支持指定深度 deep: number
watch 的 deep 选项现在支持传入数字,来指定监听的深度
const state = ref({ a: { b: { c: 1 } } }) watch(state, (newvalue) => { console.log(`state: ${newvalue}`) }, { deep: 2 } ) state.a.b = { c: 2 } // 更改了第二层的属性,触发监听 state.a.b.c = 2 // 更改了第三层的属性,不触发监听
清理函数 onwatchercleanup / oneffectcleanup
以前我们在监听函数中要发送异步请求时,很可能发生请求参数发生变化的情况,这时我们需要设置全局变量存储 abortcontroller,并在组件卸载之前清理它
import { watch, onbeforeunmount } from "vue" let controller = new abortcontroller() watch(state, (newvalue) => { controller.abort() // 取消上一次的请求 controller = new abortcontroller() fetch(`/api/${newvalue}`, { signal: controller.signal }).then(() => { // 回调逻辑 }) }); // 组件卸载前也要清理 onbeforeunmount(() => controller.abort())
现在有了清理函数 onwatchercleanup / oneffectcleanup 后,我们可以直接调用它来清理之前的 调用(异步)函数/请求
import { watch, onwatchercleanup } from 'vue' watch(id, (newid) => { const controller = new abortcontroller() fetch(`/api/${newid}`, { signal: controller.signal }).then(() => { // 回调逻辑 }) onwatchercleanup(() => { // 终止过期请求 controller.abort() }) })
oneffectcleanup 函数写法类似以上,不同的是导入来源
import { oneffectcleanup } from "@vue/reactivity";
[!warning]
onwatchercleanup 仅在 vue 3.5+ 中支持,并且必须在 watcheffect 效果函数或 watch 回调函数的同步执行期间调用:你不能在异步函数的 await 语句之后调用它。
watch 返回值增强
watch 返回值中新增 暂停/恢复侦听器,可以更细致的控制监听作用范围
const { stop, pause, resume } = watch(() => {}) // 暂停侦听器 pause() // 稍后恢复 resume()
ssr 改进
惰性激活 lazy hydration
异步组件可以通过 defineasynccomponent() api 中的 hydrate 选项来控制何时进行激活
在空闲时进行激活
import { defineasynccomponent, hydrateonidle } from 'vue' const asynccomp = defineasynccomponent({ loader: () => import('./comp.vue'), hydrate: hydrateonidle(/* 传递可选的最大超时 */) })
在元素变为可见时激活
import { defineasynccomponent, hydrateonvisible } from 'vue' const asynccomp = defineasynccomponent({ loader: () => import('./comp.vue'), hydrate: hydrateonvisible() })
自定义策略
import { defineasynccomponent, type hydrationstrategy } from 'vue' const mystrategy: hydrationstrategy = (hydrate, foreachelement) => { // foreachelement 是一个遍历组件未激活的 dom 中所有根元素的辅助函数, // 因为根元素可能是一个片段而非单个元素 foreachelement(el => { // ... }) // 准备好时调用 `hydrate` hydrate() return () => { // 如必要,返回一个销毁函数 } } const asynccomp = defineasynccomponent({ loader: () => import('./comp.vue'), hydrate: mystrategy })
其他
请查看 vue3官方文档 - 惰性激活,这里不再赘述
useid() 生成唯一应用id
用于为无障碍属性或表单元素生成每个应用内唯一的 id。在我们日常应用中,主要可以解决服务端和客户端生成的id不一样导致渲染报错的问题
<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
如果客户端值不可避免地与其服务端对应值(例如日期)不同,我们可以使用属性 data-allow-mismatch 来避免由此产生的激活不匹配警告
<span data-allow-mismatch>{{ data.tolocalestring() }}</span>
还可以指定特定类型。允许的值有:text,children (仅允许直接子组件不匹配),class,style,attribute
其他
usetemplateref()
返回一个浅层 ref,可以更直观的绑定元素,同时也支持动态绑定
<script setup> import { ref, usetemplateref, onmounted } from 'vue' const targetref = ref('input1') const inputref = usetemplateref<htmlinputelement>(targetref.value) onmounted(() => { inputref.value.focus() }) </script> <template> <input ref="input1" /> <input ref="input2" /> </template>
其他不常用的就不在说明了
到此这篇关于一文带你掌握 vue3.5常用特性的文章就介绍到这了,更多相关vue3.5常用特性内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论