美文网首页
Vue 3.5发布

Vue 3.5发布

作者: 涅槃快乐是金 | 来源:发表于2024-09-12 00:09 被阅读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 版本提供了一个可选设置,可以为它们启用内联提示:

    解构属性的内联提示

    详细信息:

    • 查看使用和注意事项的文档
    • 参阅 RFC#502,了解该功能的历史和设计原理。

    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 编写自定义元素添加了许多新功能:

    • 通过 configureApp 选项支持为自定义元素配置应用程序。
    • 添加了 useHost()useShadowRoot()this.$host API,用于访问自定义元素的主机元素和 Shadow Root。
    • 支持通过传递 shadowRoot: false 来挂载没有 Shadow DOM 的自定义元素。
    • 支持提供 nonce 选项,该选项将附加到自定义元素注入的 <style> 标签。

    这些新的仅限自定义元素选项可以通过第二个参数传递给 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

    相关文章

      网友评论

          本文标题:Vue 3.5发布

          本文链接:https://www.haomeiwen.com/subject/dubpljtx.html