写点什么

Vue3.5 常用特性整理

  • 2025-01-25
    福建
  • 本文字数:2581 字

    阅读完需:约 8 分钟

Vue3.5 发布已近半年,抽空整理下常用的新增/改动特性


响应式 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>
复制代码


还可以指定特定类型。允许的值有:textchildren (仅允许直接子组件不匹配),classstyleattribute


其他


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>
复制代码


其他不常用的就不在说明了


文章转载自:唯之为之

原文链接:https://www.cnblogs.com/weizwz/p/18689185

体验地址:http://www.jnpfsoft.com/?from=001YH

用户头像

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
Vue3.5常用特性整理_JavaScript_不在线第一只蜗牛_InfoQ写作社区