Vue3.5正式上线,有哪些新特性和用法?

在这里插入图片描述
9月1日, Vue 3.5 正式发布了!

此次要版本不包含重大更改,并且包括内部改进和有用的新功能。我们将在这篇博文中介绍一些亮点 - 有关更改和新功能的完整列表,请参阅 GitHub 上的完整更新日志。

1. Props 解构

在vue3.5 之前,如果将props直接进行解构,是会失去响应式的,解构出来的值实际上是一个常量。如果需要监听变化,则需要配合toRefs一起使用。

之前的props声明方式:

const props = withDefaults(
  defineProps<{
    count?: number
    msg?: string
  }>(),
  {
    count: 0,
    msg: 'hello'
  }
)

vue3.5现在可以简化声明:解构的同时还会保持其响应式。

const { count = 0, msg = 'hello' } = defineProps<{
  count?: number
  message?: string
}>()

在 3.5 及以上版本中,当同一个 <script setup> 块中的代码访问从 defineProps 解构的变量时(例如 count),Vue 的编译器会自动的访问编译为 props.count

使用watch监听解构后的props时,如果按以下这样写,是将一个值而不是响应式数据源传递给 watch。事实上,Vue 的编译器会捕获这种情况并抛出警告。

const { foo } = defineProps(['foo'])

watch(foo, /* ... */)

监听解构后props的正确写法

watch(() => foo, /* ... */)

2. 元素ref的定义

在 3.5 之前,我们可以使用变量名称与 静态ref 属性匹配的普通 refs。旧方法要求 ref 属性可由编译器分析,因此仅限于静态 ref 属性。

<script setup>
const inputRef = ref('input')
</script>

<template>
  <input ref="input">
</template>

相比之下,useTemplateRef() 通过运行时字符串匹配 refs,因此支持动态 ref 的使用场景。

<script setup>
import { useTemplateRef } from 'vue'

const inputRef = useTemplateRef('input')
</script>

<template>
  <input ref="input">
</template>

3. Teleport 支持延迟

当使用 Teleport 组件时,指定的目标元素(即 to 属性所指向的选择器对应的元素)必须在页面的 DOM(文档对象模型)结构中已经存在,否则 Teleport 就无法将内容传送过去。

比如,如果你使用 <teleport to="#my-target">,但页面中没有一个具有 id=“my-target” 的元素,Teleport 就无法正常工作,因为找不到传送内容的目标位置。

但vue3.5中可以通过defer来延迟Teleport 的挂载,它会等到同一更新周期中的所有其他 DOM 内容都渲染完毕后,再定位目标容器并挂载其子容器。

<Teleport defer to="#target">...</Teleport>
<div id="target"></div>

下面这样写就会找不到目标元素,因为在组件渲染的顺序上,<Teleport> 组件会先尝试查找目标位置,而此时 <div id="target"></div> 还没有被渲染出来。

<Teleport to="#target">...</Teleport>
<div id="target"></div>

4. watch清理回调

有时我们可能会在 watcher 中执行副作用,例如异步请求

watch(id, (newId) => {
  fetch(`/api/${newId}`).then(() => {
    //  回调事件
  })
})

但是,如果 id 在请求完成之前发生更改,该怎么办?当上一个请求完成时,它仍将触发 ID 值已过时的回调。理想情况下,我们希望能够在 id 更改为新值时取消过时的请求。

我们可以使用onWatcherCleanup() 来注册一个清理函数,该函数将在观察程序失效并即将重新运行时调用:

import { watch, onWatcherCleanup } from 'vue'

watch(id, (newId) => {
  const controller = new AbortController()

  fetch(`/api/${newId}`, { signal: controller.signal }).then(() => {
    // 回调事件
  })
  
  onWatcherCleanup(() => {
    // 如果 id 在请求完成之前发生更改,会取消之前的请求
    controller.abort()
  })
})

注意:onWatcherCleanup 仅在 Vue 3.5+ 中受支持,并且必须在同步执行 watchEffect 函数或 watch 回调函数期间调用:不能在异步函数中的 await 语句之后调用它。

vue3.5之前中也可以使用onCleanup 函数作为第 3 个参数传递给watch函数:

watch(id, (newId, oldId, onCleanup) => {
  // ...
  onCleanup(() => {
    // 清除逻辑
  })
})

watchEffect((onCleanup) => {
  // ...
  onCleanup(() => {
    // 清除逻辑
  })
})

还有一些SSR 和自定义元素相关的改进,文中没有提到,有关 3.5 中更改和功能的完整列表,请查看 GitHub 上的完整更改日志

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值