提前解锁 Vue 3.5 的新特性

Vue 3.5 是 Vue.js 新发布的版本,虽然没有引入重大变更,但带来了许多实用的增强功能、内部优化和性能改进。

1. 响应式系统优化

Vue 3.5 进一步优化了响应式系统的性能,并且减少内存占用。尤其在处理大型或深度嵌套的响应式数组时,性能提高了 10 倍。

举个 🌰

html 复制代码
<template>
  <div>
    <p v-for="item in deepArray" :key="item.value">{{ item.value }}</p>
  </div>
</template>

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

// 创建一个大型的深度嵌套数组,测试响应式系统的优化效果
const deepArray = reactive([...Array(10000)].map(() => reactive({ value: Math.random() })))
</script>

在这个示例中,我们创建了一个包含 10000 个深度嵌套对象的数组。Vue 3.5 对这种场景的内存和性能进行了优化,可以在大量操作和变化时观察到更流畅的响应式处理。

2. 响应式 Props 解构

在 Vue 3.5 中,响应式 props 解构默认启用。在使用 defineProps 时,可以像处理普通 JavaScript 对象那样解构 props,并且解构后的变量保持响应式。

之前的方式:

javascript 复制代码
const props = withDefaults(
  defineProps<{ count?: number; msg?: string }>(),
  { count: 0, msg: 'hello' }
)

新方式:

javascript 复制代码
const { count = 0, msg = 'hello' } = defineProps<{ count?: number; msg?: string }>()

解构后的变量 count 和 msg 在模板中使用时会自动保持响应式,且不需要显式地调用 toRefs。

但我没有成功在 Vue 3.5 的项目下运行成功,还需要研究一下 o(╥﹏╥)o。

3. 服务器渲染(SSR)改进

3.1 懒加载补水(Lazy Hydration)

Vue 3.5 引入了懒加载补水功能,使用 defineAsyncComponent() 可以控制异步组件的水合时机。例如:允许异步组件在首次可见时才进行补水操作,减少初次渲染的资源消耗。

3.1.1解释一下补水(水合操作)!!

补水(Hydration)是一个与**服务器端渲染(SSR)相关的术语。**

****在 SSR 中,Vue 会在服务器上预先渲染组件的 HTML,并将其发送到浏览器。当页面加载时,客户端的 JavaScript 代码会接管 这些已经存在的 HTML 元素,并将它们变为动态响应式 ,这个过程就被称为水合操作(Hydration)

补水(水合操作)的意义

水合操作的主要目的是将服务器端预渲染的静态 HTML客户端的动态 JavaScript 逻辑 连接起来,使页面在首次加载时可以快速显示内容,同时在客户端加载完 JavaScript 之后,页面可以正常交互。这种做法提高了页面的首次加载速度用户体验,特别是在网络环境较差或页面较为复杂时。

补水与懒加载补水

1、普通补水

页面加载时,所有的静态 HTML 会立即被客户端 JavaScript "接管"。这种做法可能会导致在页面初次渲染时,客户端需要同时处理大量的水合任务,从而影响性能。

2、懒加载补水

Vue 3.5 引入的懒加载补水功能指,只在组件首次出现在视口中时才进行水合操作。这样可以减少页面初次渲染时的性能开销,只在需要时才补水,特别适合异步加载的组件或在页面滚动到可见区域时才需要的内容。

举个 🌰

假设我们有一个异步加载的组件 AsyncComponent.vue,在普通补水情况下,这个组件在 SSR 中生成的 HTML 会在页面加载时立即被水合,无论用户是否滚动到该组件的可见区域。而在懒加载补水的情况下,只有当用户滚动到组件可见时,才会触发水合。

App.vue

html 复制代码
<template>
  <div class="container">
    <AsyncComp v-if="visible" />
    <button @click="toggleVisibility">Toggle Component</button>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { defineAsyncComponent, hydrateOnVisible } from 'vue'

const visible = ref(false)
const toggleVisibility = () => {
  visible.value = !visible.value
}
const AsyncComp = defineAsyncComponent({
  loader: () => import('./components/AsyncComponent.vue'), // 模拟异步加载的组件
  hydrate: hydrateOnVisible() // 只有在组件可见时才进行水合
})
</script>

AsyncComponent.vue

html 复制代码
<template>
  <div>
    异步加载的组件
  </div>
</template>

展示为:

3.2 useId( ) API

useId( ) 是一个新 API,专门为生成在服务器和客户端渲染过程中保持稳定的唯一 ID。这对于生成表单元素和可访问性属性的 ID 非常有用。

举个 🌰

html 复制代码
<template>
  <form>
    <label :for="id">Name:</label>
    <input :id="id" type="text" />
  </form>
</template>

<script setup>
import { useId } from 'vue'
// 使用 useId 生成一个唯一的 id
const id = useId()
console.log("~ id:", id)
</script>

此功能确保生成的 ID 在 SSR 和客户端渲染时保持一致,确保表单和可访问性属性不会因不匹配导致警告或错误。

4. 自定义元素改进

Vue 3.5 对 defineCustomElement() API 进行了增强,使 Vue 创建 Web Components 更加灵活。

举个 🌰 App.vue

html 复制代码
<template>
  <div class="container">
    <!-- Vue 自定义元素可以像普通 HTML 元素一样使用 -->
    <my-element title="使用自定义元素" description="这是通过 Vue 定义的 Web Component。"></my-element>
    <br />
    <my-element />
  </div>
</template>

<script setup>
import { defineCustomElement } from 'vue'
import MyElement from './components/MyElement.ce.vue'

// 使用 defineCustomElement 注册组件
const MyElementCustom = defineCustomElement(MyElement, {
  shadowRoot: false,
})
// 通过 customElements.define 注册为自定义元素
customElements.define('my-element', MyElementCustom)
</script>

MyElement.ce.vue

html 复制代码
<template>
  <div>
    <h1>{{ title }}</h1>
    <p>{{ description }}</p>
  </div>
</template>

<script>
export default {
  props: {
    title: {
      type: String,
      default: '默认标题'
    },
    description: {
      type: String,
      default: '这是自定义元素的描述内容'
    }
  }
}
</script>

展示为:

4.1 解释一下 .ce.vue

在 Vue.js 中,.ce.vue 文件名 中的**.ce** 通常表示自定义元素(Custom Element) 。这种命名方式并不是 Vue 官方强制要求的,而是一种约定俗成的命名规范 ,用于区分普通的 Vue 组件和用来创建Web Components的自定义元素组件。

自定义元素在许多场景中很有用,特别是希望在多个框架之间共享组件,或者希望组件能够独立运行时,Web Components 是一个很好的选择。而 .ce.vue 文件命名则帮助开发者清楚地知道这个 Vue 组件是为生成 Web Components 而设计的。

5. 新增 useTemplateRef( )

Vue 3.5 引入了 useTemplateRef() API,它允许动态地获取模板引用,特别适用于引用 ID 动态变化或条件变化的场景。相较于传统的 ref,useTemplateRef 可以在运行时根据不同的条件动态更新引用,而不是依赖于静态的 ref 属性。

举个 🌰

html 复制代码
<template>
  <input ref="inputRef" type="text" />
</template>

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

// 获取动态引用的 input
const inputRef = useTemplateRef('inputRef')

// 在生命周期中可以访问这个引用
onMounted(() => {
  inputRef.value.focus()
})
</script>

6. 延迟传送(defer Teleport)

Vue 内置 <Teleport> 组件在传送内容时,要求目标元素在组件挂载时已经存在。Vue 3.5 引入了 defer 属性,许传送内容到后才渲染的目标元素。

举个 🌰

html 复制代码
<template>
  <div class="container">
    <Teleport defer to="#dynamic-target">
      <p>传送内容...</p>
    </Teleport>
    <div id="dynamic-target"></div>
  </div>
</template>

<script setup>
import { onMounted } from 'vue'
onMounted(() => {
  setTimeout(() => {
    // 模拟目标元素动态渲染
    document.getElementById('dynamic-target').innerHTML = '<div>目标元素已渲染</div>'
  }, 1000)
})
</script>

展示为:

这里 Teleport 组件会等待目标元素(#dynamic-target)渲染后再将内容传送过去,可以解决传送目标先于组件渲染的问题。

7. 新增 onWatcherCleanUp()

Vue 3.5 引入了 onWatcherCleanup() API,用于在清理 watch 时注册回调函数。例如,可以在 watch 的回调中清理过时的网络请求。

举个 🌰

html 复制代码
<template>
  <div>
    <button @click="id++">更改 ID</button>
    <p>当前 ID: {{ id }}</p>
  </div>
</template>

<script setup>
import { ref, watch, onWatcherCleanup } from 'vue';

const id = ref(1);
// 监控 id 的变化,并在 watcher 停止时清理过时的网络请求
watch(id, (newId) => {
  const controller = new AbortController();
  // 发起网络请求
  fetch(`/api/data/${newId}`, { signal: controller.signal })
    .then((response) => {
      if (!response.ok) {
        throw new Error(`网络请求失败: ${response.status}`);
      }
      return response.json(); // 解析 JSON
    })
    .then((data) => {
      console.log('获取的数据:', data);
    })
    .catch((error) => {
      if (error.name === 'AbortError') {
        console.log('请求被取消');
      } else {
        console.error('发生错误:', error);
      }
    });
  // 注册清理函数,取消旧的请求
  onWatcherCleanup(() => {
    controller.abort();
  });
});
</script>

此功能允许在 watch 停止追踪时自动执行清理操作,避免资源泄漏。

8. 总结

Vue 3.5 版本提供了多项增强功能,包括响应式系统的性能优化、响应式 props 解构、SSR 改进、自定义元素支持的扩展等,优化内存、提升性能的同时也提升了 Vue 的开发体验。

有些内容可能不是很详细,大家感兴趣的话,可以自行研究一下。

在此之前:需要确保项目使用的是 Vue 3.5。可以使用以下命令更新项目中的 Vue 版本:

bash 复制代码
npm install vue@latest
# or
yarn add vue@latest

然后,检查项目中的 package.json,确认 Vue 版本已经更新到 3.5 或更高:

相关推荐
谢尔登6 分钟前
Webpack 和 Vite 的区别
前端·webpack·node.js
谢尔登7 分钟前
【Webpack】Tree Shaking
前端·webpack·node.js
过期的H2O223 分钟前
【H2O2|全栈】关于CSS(4)CSS基础(四)
前端·css
纳尼亚awsl36 分钟前
无限滚动组件封装(vue+vant)
前端·javascript·vue.js
八了个戒41 分钟前
【TypeScript入坑】TypeScript 的复杂类型「Interface 接口、class类、Enum枚举、Generics泛型、类型断言」
开发语言·前端·javascript·面试·typescript
西瓜本瓜@44 分钟前
React + React Image支持图像的各种转换,如圆形、模糊等效果吗?
前端·react.js·前端框架
黄毛火烧雪下1 小时前
React 的 useEffect 钩子,执行一些异步操作来加载基本信息
前端·chrome·react.js
蓝莓味柯基1 小时前
React——点击事件函数调用问题
前端·javascript·react.js
资深前端之路1 小时前
react jsx
前端·react.js·前端框架
cc蒲公英1 小时前
vue2中使用vue-office库预览pdf /docx/excel文件
前端·vue.js