Vue 3.5发布

2024-09-12  本文已影响0人  涅槃快乐是金

今天,我们非常兴奋地宣布发布 Vue 3.5 "Tengen Toppa Gurren Lagann"!

这是一个小版本更新,不包含破坏性变更,同时包含内部改进和有用的新功能。我们将在这篇博客文章中介绍一些亮点——完整的更改和新功能列表请参阅 GitHub 上的完整更新日志。

响应式系统优化

在 3.5 版本中,Vue 的响应式系统进行了又一次重大重构,在没有行为变更的情况下,性能得到了提升,内存使用显著改善(减少了 56%)。此重构还解决了 SSR 中由于悬挂计算属性导致的过时计算值和内存问题。

此外,3.5 版本还针对大型、深度响应式数组优化了反应式跟踪,在某些情况下,使这些操作的速度提高了 10 倍。

详细信息:PR#10397, PR#9511

响应式属性解构

响应式属性解构在 3.5 版本中已被稳定下来。该功能现在默认启用,通过 <script setup> 中的 defineProps 调用解构的变量现在是响应式的。尤其值得注意的是,通过利用 JavaScript 的原生默认值语法,该功能大大简化了具有默认值的属性声明:

之前

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

之后

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

通过编译器,访问解构的变量(如 count)会自动编译为 props.count,因此它们会在访问时被跟踪。类似于 props.count,如果要监视解构后的属性变量或将其传递给组合函数以保持响应性,则需要将其包装在 getter 中:

watch(count /* ... */)
//    ^ 编译时会出现错误

watch(() => count /* ... */)
//    ^ 包装在 getter 中,正常工作

// 组合函数应使用 `toValue()` 来标准化输入
useDynamicCount(() => count)

对于那些希望更好地区分解构属性和普通变量的人,@vue/language-tools 2.1 版本提供了一个可选设置,可以为它们启用内联提示:

解构属性的内联提示

详细信息:

SSR(服务端渲染)改进

3.5 带来了几项长期请求的服务端渲染改进。

懒加载 Hydration

异步组件现在可以通过 defineAsyncComponent() API 的 hydrate 选项指定何时进行 Hydration。例如,只在组件可见时进行 Hydration:

import { defineAsyncComponent, hydrateOnVisible } from 'vue'

const AsyncComp = defineAsyncComponent({
  loader: () => import('./Comp.vue'),
  hydrate: hydrateOnVisible()
})

核心 API 刻意保持低级别,Nuxt 团队已经在此功能之上构建了更高级别的语法糖。

详细信息:PR#11458

useId()

useId() 是一个 API,用于生成在服务器和客户端渲染之间保证稳定的唯一应用程序 ID。这些 ID 可以用于表单元素和可访问性属性,并且在 SSR 应用程序中使用时不会导致 Hydration 不匹配:

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

const id = useId()
</script>

<template>
  <form>
    <label :for="id">姓名:</label>
    <input :id="id" type="text" />
  </form>
</template>

详细信息:PR#11404

data-allow-mismatch

在客户端值不可避免地与服务器值不同(例如日期)时,我们现在可以使用 data-allow-mismatch 属性来抑制结果中的 Hydration 不匹配警告:

<span data-allow-mismatch>{{ data.toLocaleString() }}</span>

您还可以通过为属性提供值来限制允许的 mismatch 类型,可能的值包括 textchildrenclassstyleattribute

自定义元素改进

3.5 修复了许多与 defineCustomElement() API 相关的长期问题,并为使用 Vue 编写自定义元素添加了许多新功能:

这些新的仅限自定义元素选项可以通过第二个参数传递给 defineCustomElement

import MyElement from './MyElement.ce.vue'

defineCustomElements(MyElement, {
  shadowRoot: false,
  nonce: 'xxx',
  configureApp(app) {
    app.config.errorHandler = ...
  }
})

其他显著功能

useTemplateRef()

3.5 引入了一种通过 useTemplateRef() API 获取 Template Refs 的新方法:

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

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

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

在 3.5 之前,我们推荐使用变量名与静态 ref 属性匹配的普通 refs。旧方法要求 ref 属性能够被编译器分析,因此仅限于静态 ref 属性。相比之下,useTemplateRef() 通过运行时字符串 ID 匹配 refs,因此支持动态 ref 绑定到变化的 ID。

@vue/language-tools 2.1 也为新语法实现了特殊支持,因此在使用 useTemplateRef() 时,您会根据模板中 ref 属性的存在获得自动完成和警告:

解构属性的内联提示

延迟传送(Deferred Teleport)

内置 <Teleport> 组件的已知限制是其目标元素必须在传送组件挂载时存在。这阻止了用户将内容传送到 Vue 渲染的其他元素中。

在 3.5 中,我们引入了 <Teleport>defer 属性,它在当前渲染周期后挂载,因此现在可以这样使用:

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

这种行为需要 defer 属性,因为默认行为需要向后兼容。

详细信息:PR#11387

onWatcherCleanup()

3.5 引入了一个全局导入的 API onWatcherCleanup(),用于在观察者中注册清理回调:

import { watch, onWatcherCleanup } from 'vue'

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

  fetch(`/api/${newId}`, { signal: controller.signal }).then(() => {
    // 回调逻辑
  })

  onWatcherCleanup(() => {
    // 终止过时的请求
    controller.abort()
  })
})

相关:新文档部分关于副作用清理

原文:https://blog.vuejs.org/posts/vue-3-5

上一篇 下一篇

猜你喜欢

热点阅读