提前解锁 Vue 3.5 的新特性

news2024/11/15 21:37:16

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

1. 响应式系统优化

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

举个 🌰

<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,并且解构后的变量保持响应式。

之前的方式:

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

新方式:

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

<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  

<template>
  <div>
    异步加载的组件
  </div>
</template>

展示为:

3.2 useId( ) API

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

举个 🌰

<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

<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

<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 属性。

举个 🌰

<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 属性,许传送内容到后才渲染的目标元素。

举个 🌰

<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 的回调中清理过时的网络请求。

举个 🌰

<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 版本:

npm install vue@latest
# or
yarn add vue@latest

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2151227.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2024 新手指南:轻松掌握 Win10 的录屏操作

之前为了节约成本我们公司都采用录制软件操作都方式来为异地的同事进行远程操作培训的。所以我们尝试了不少的录屏工具&#xff0c;这里我就分享下win10怎么录屏的操作过程。 1.福昕录屏大师 链接&#xff1a;www.foxitsoftware.cn/REC/ 这款录屏工具是初学者的理想之选&…

【STL】map和set相关知识详细梳理

1. 预备知识 1.1 关联式容器 在之前&#xff0c;我们已经接触过STL中的部分容器&#xff0c;比如&#xff1a;vector、list、deque、 forward_list(C11)等&#xff0c;这些容器统称为序列式容器&#xff0c;因为其底层为线性序列的数据结构&#xff0c;里面 存储的是元素本身。…

Git之如何删除Untracked文件(六十八)

简介&#xff1a; CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布&#xff1a;《Android系统多媒体进阶实战》&#x1f680; 优质专栏&#xff1a; Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a; 多媒体系统工程师系列【…

PCL 点云圆柱邻域搜索

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 2.2完整代码 三、实现效果 PCL点云算法汇总及实战案例汇总的目录地址链接&#xff1a; PCL点云算法与项目实战案例汇总&#xff08;长期更新&#xff09; 一、概述 本文将介绍如何使用PCL库进…

L3 逻辑回归

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 在周将使用 LogisticRegression 函数对经典的鸢尾花 (Iris) 数据集进行分类。将详细介绍逻辑回归的数学原理。 1. 逻辑回归的数学原理 逻辑回归是一种线性分…

海外大带宽服务器连接失败怎么办?

在全球化日益加深的今天&#xff0c;海外大带宽服务器已成为企业拓展国际市场、提升业务效率的重要工具。然而&#xff0c;面对复杂多变的网络环境和技术挑战&#xff0c;服务器连接失败的问题时有发生&#xff0c;这不仅影响了企业的正常运营&#xff0c;还可能带来经济损失和…

R语言机器学习算法实战系列(二) SVM算法(Support Vector Machine)

文章目录 介绍原理应用方向下载数据加载R包导入数据数据预处理数据描述数据切割标准化数据设置参数训练模型预测测试数据评估模型模型准确性混淆矩阵模型评估指标ROC CurvePRC Curve特征的重要性保存模型总结系统信息介绍 支持向量机(Support Vector Machine,简称SVM)是一种…

JavaScript发送邮件:实现前端触发的教程?

JavaScript发送邮件的方式&#xff1f;怎么使用JavaScript发信&#xff1f; 无论是用户反馈、联系表单还是自动通知&#xff0c;前端触发的邮件发送功能都能极大地提升用户体验。AokSend将详细介绍如何通过JavaScript发送邮件&#xff0c;实现前端触发的邮件发送功能。 JavaS…

58.【C语言】内存函数(memcpy函数)

目录 1.memcpy *简单使用 翻译: *模拟实现 注意事项: *例题 1.memcpy *简单使用 memcpy:memory copy cplusplus的介绍 点我跳转 翻译: 函数 memcpy void * memcpy ( void * destination, const void * source, size_t num ); 复制内存块 直接从source指向的位置复制num…

SpringBoot开发-数据加密

提示&#xff1a;本篇文章介绍各种加密工具以及数据脱密工具的使用 文章目录 前言一、AES加密算法二、AES加密算法工具使用&#xff08;一&#xff09;引入依赖&#xff08;二&#xff09;编写工具类&#xff08;三&#xff09;测试 三、MD5加密算法四、MD5加密工具使用&#x…

Windows【环境 01】服务器系统重装后的服务恢复(ES\Redis\Jafka\Tomcat)环境变量和服务注册

服务器系统重装后的服务恢复 1.原因2.问题处理2.1 JDK2.2 Elasticsearch2.3 Redis2.4 Jafka2.5 Tomcat 3.总结 1.原因 Windows 服务器系统盘损坏&#xff0c;换了硬盘并重做了系统&#xff0c;其他磁盘未损坏但安装的服务无法正常运行了&#xff0c;包括&#xff1a; Elastic…

莱卡相机sd内存卡格式化了怎么恢复数据

在数字化时代&#xff0c;相机已成为我们记录生活、捕捉瞬间的重要设备。而SD内存卡&#xff0c;作为相机的存储媒介&#xff0c;承载着我们的珍贵记忆和重要数据。然而&#xff0c;有时由于误操作、系统错误或其他原因&#xff0c;我们可能会不小心格式化SD内存卡&#xff0c;…

Windows11自带截图工具的录屏功能

WinShiftS打开截图工具。 点击工具栏上的“录屏”按钮&#xff0c;或者按下WinAltR组合键。启动录屏模式&#xff0c;并允许你开始录制屏幕内容。 可以选择录制整个屏幕还是只录制一个特定的窗口。此外&#xff0c;还可以设置录制视频的分辨率和帧率。如果希望录制屏幕上的音…

在 deepin 上除了 Steam,还能怎么玩游戏?

查看原文 前段时间&#xff0c;很多朋友在 deepin 23 上实现了《黑神话&#xff1a;悟空》的通关&#xff0c;那么除了通过 Steam 玩 Windows 游戏之外&#xff0c;还有其他可以使用的游戏平台吗&#xff1f; 回答&#xff0c;当然是可以哒&#xff01; 游戏平台介绍 今天介…

每日OJ题_牛客_WY22 Fibonacci数列(斐波那契)

目录 牛客_WY22 Fibonacci数列&#xff08;斐波那契&#xff09; 解析代码 牛客_WY22 Fibonacci数列&#xff08;斐波那契&#xff09; Fibonacci数列_牛客题霸_牛客网 解析代码 求斐波那契数列的过程中&#xff0c;判断⼀下&#xff1a;何时 n 会在两个 fib 数之间。 #in…

拥塞控制算法的 rtt 公平性

我强调过&#xff0c;拥塞控制的核心在公平可用性&#xff0c;公平性由 buffer 动力学保证&#xff0c;而 buffer 动力学有两种表现形式&#xff1a; buffer 占比决定带宽占比&#xff0c;以 aimd 为例&#xff1b;带宽越小&#xff0c;buffer 挤兑加速比越大&#xff0c;以 b…

HTTP中的event-stream,eventsource,SSE,chatgpt,stream request,golang

我们都知道chatgpt是生成式的&#xff0c;因此它返回给客户端的消息也是一段一段的&#xff0c;所以普通的HTTP协议无法满足&#xff0c;当然websocket是能满足的&#xff0c;但是这个是双向的通信&#xff0c;其实 SSE&#xff08;Server-Sent Events&#xff09; 正好满足这个…

树与图的深度优先遍历(dfs的图论中的应用)

模板题 846. 树的重心 给定一颗树&#xff0c;树中包含 nn 个结点&#xff08;编号 1∼n&#xff09;和 n−1条无向边。 请你找到树的重心&#xff0c;并输出将重心删除后&#xff0c;剩余各个连通块中点数的最大值。 重心定义&#xff1a;重心是指树中的一个结点&#xff…

RabbitMQ 高级特性——发送方确认

文章目录 前言发送方确认confirm 确认模式return 退回模式 常见面试题 前言 前面我们学习了 RabbitMQ 中交换机、队列和消息的持久化&#xff0c;这样能够保证存储在 RabbitMQ Broker 中的交换机和队列中的消息实现持久化&#xff0c;就算 RabbitMQ 服务发生了重启或者是宕机&…

【Android】浅析MVC与MVP

【Android】浅析MVC与MVP 什么是架构&#xff1f; 架构&#xff08;Architecture&#xff09;在软件开发中指的是软件系统的整体设计和结构&#xff0c;它描述了系统的高层组织方式&#xff0c;包括系统中各个组件之间的关系、依赖、交互方式&#xff0c;以及这些组件如何协同…