一文带你掌握 Vue3.5常用特性

 更新时间:2025年01月24日 10:38:21   作者:唯之为之  
Vue3.5 发布已近半年,这篇文章主要来和大家技术一下它常用的新增和改动特性,文中的示例代码讲解详细,有需要的小伙伴可以跟随小编一起学习一下

响应式 Props 解构

Vue3.5 中 Props 正式支持解构了,并添加了响应式跟踪

设置默认值

使用 JavaScript 原生的默认值语法声明 props 默认值

以前

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

现在

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

响应式解构

当在同一个 <script setup> 代码块中访问由 defineProps 解构的变量时,Vue 编译器会自动在前面添加 props

以前

const { foo } = defineProps(['foo'])
 
watchEffect(() => {
  // 在 3.5 之前只运行一次
  console.log(foo)
})

现在

const { foo } = defineProps(['foo'])
 
watchEffect(() => {
  // 在 3.5 中在 "foo" prop 变化时重新执行
  console.log(foo)
  // `foo` 由编译器转换为 `props.foo`,以上等同于 `console.log(props.foo)`
})

与之类似,监听解构的 prop 变量 或 将其传递到可组合项中同时保留响应性 时需要将其包装在 getter 中

以前

const { foo } = defineProps(['foo'])
 
watch(foo, /* ... */)

现在:

// watch(foo, /* ... */) 等价于 watch(props.foo, ...),我们给 watch 传递的是一个值而不是响应式数据源
watch(() => foo, /* ... */)
 
// 传递解构的 prop 到外部函数中并保持响应性
useComposable(() => foo)

监听(watch / watcheffect) 相关

watch 支持指定深度 deep: number

watch 的 deep 选项现在支持传入数字,来指定监听的深度

const state = ref({
  a: {
    b: {
      c: 1
    }
  }
})
 
watch(state, (newValue) => {
    console.log(`state: ${newValue}`)
  },
  { deep: 2 }
)
 
state.a.b = { c: 2 } // 更改了第二层的属性,触发监听
state.a.b.c = 2 // 更改了第三层的属性,不触发监听

清理函数 onWatcherCleanup / onEffectCleanup

以前我们在监听函数中要发送异步请求时,很可能发生请求参数发生变化的情况,这时我们需要设置全局变量存储 AbortController,并在组件卸载之前清理它

import { watch, onBeforeUnmount } from "vue"
 
let controller = new AbortController()
 
watch(state, (newValue) => {
    controller.abort() // 取消上一次的请求
    controller = new AbortController()
 
    fetch(`/api/${newValue}`, { signal: controller.signal }).then(() => {
    // 回调逻辑
  })
});
 
// 组件卸载前也要清理
onBeforeUnmount(() => controller.abort())

现在有了清理函数 onWatcherCleanup / onEffectCleanup 后,我们可以直接调用它来清理之前的 调用(异步)函数/请求

import { watch, onWatcherCleanup } from 'vue'
 
watch(id, (newId) => {
  const controller = new AbortController()
 
  fetch(`/api/${newId}`, { signal: controller.signal }).then(() => {
    // 回调逻辑
  })
 
  onWatcherCleanup(() => {
    // 终止过期请求
    controller.abort()
  })
})

onEffectCleanup 函数写法类似以上,不同的是导入来源

import { onEffectCleanup } from "@vue/reactivity";

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

watch 返回值增强

watch 返回值中新增 暂停/恢复侦听器,可以更细致的控制监听作用范围

const { stop, pause, resume } = watch(() => {})
 
// 暂停侦听器
pause()
 
// 稍后恢复
resume()

SSR 改进

惰性激活 Lazy Hydration

异步组件可以通过 defineAsyncComponent() API 中的 hydrate 选项来控制何时进行激活

在空闲时进行激活

import { defineAsyncComponent, hydrateOnIdle } from 'vue'
 
const AsyncComp = defineAsyncComponent({
  loader: () => import('./Comp.vue'),
  hydrate: hydrateOnIdle(/* 传递可选的最大超时 */)
})

在元素变为可见时激活

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

自定义策略

import { defineAsyncComponent, type HydrationStrategy } from 'vue'
 
const myStrategy: HydrationStrategy = (hydrate, forEachElement) => {
  // forEachElement 是一个遍历组件未激活的 DOM 中所有根元素的辅助函数,
  // 因为根元素可能是一个片段而非单个元素
  forEachElement(el => {
    // ...
  })
  // 准备好时调用 `hydrate`
  hydrate()
  return () => {
    // 如必要,返回一个销毁函数
  }
}
 
const AsyncComp = defineAsyncComponent({
  loader: () => import('./Comp.vue'),
  hydrate: myStrategy
})

其他

请查看 Vue3官方文档 - 惰性激活,这里不再赘述

useId() 生成唯一应用ID

用于为无障碍属性或表单元素生成每个应用内唯一的 ID。在我们日常应用中,主要可以解决服务端和客户端生成的id不一样导致渲染报错的问题

<script setup>
import { useId } from 'vue'
 
const id = useId()
</script>
 
<template>
  <form>
    <label :for="id">Name:</label>
    <input :id="id" type="text" />
  </form>
</template>

data-allow-mismatch

如果客户端值不可避免地与其服务端对应值(例如日期)不同,我们可以使用属性 data-allow-mismatch 来避免由此产生的激活不匹配警告

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

还可以指定特定类型。允许的值有:text,children (仅允许直接子组件不匹配),class,style,attribute

其他

useTemplateRef()

返回一个浅层 ref,可以更直观的绑定元素,同时也支持动态绑定

<script setup>
import { ref, useTemplateRef, onMounted } from 'vue'
 
const targetRef = ref('input1')
const inputRef = useTemplateRef<HTMLInputElement>(targetRef.value)
 
onMounted(() => {
  inputRef.value.focus()
})
</script>
 
<template>
  <input ref="input1" />
    <input ref="input2" />
</template>

其他不常用的就不在说明了

到此这篇关于一文带你掌握 Vue3.5常用特性的文章就介绍到这了,更多相关Vue3.5常用特性内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Vue-Element-Admin前端接入SSO的方法步骤

    Vue-Element-Admin前端接入SSO的方法步骤

    本文主要介绍了Vue-Element-Admin前端接入SSO的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-04-04
  • Antd-vue Table组件添加Click事件,实现点击某行数据教程

    Antd-vue Table组件添加Click事件,实现点击某行数据教程

    这篇文章主要介绍了Antd-vue Table组件添加Click事件,实现点击某行数据教程,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11
  • vue组件三大核心概念图文详解

    vue组件三大核心概念图文详解

    本文主要介绍属性、事件和插槽这三个vue基础概念、使用方法及其容易被忽略的一些重要细节,感兴趣的朋友跟随小编一起看看吧
    2019-05-05
  • Vue编译报错内存溢出问题解决方式

    Vue编译报错内存溢出问题解决方式

    这篇文章主要为大家介绍了Vue编译报错内存溢出问题解决方式,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08
  • 结合mint-ui移动端下拉加载实践方法总结

    结合mint-ui移动端下拉加载实践方法总结

    下面小编就为大家带来一篇结合mint-ui移动端下拉加载实践方法总结。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-11-11
  • Vue中video标签如何实现不静音自动播放

    Vue中video标签如何实现不静音自动播放

    最近在做大屏展示需要在一开始播放引导视频,产生自动播放需求,下面这篇文章主要给大家介绍了关于Vue中video标签如何实现不静音自动播放的相关资料,需要的朋友可以参考下
    2023-01-01
  • Element Breadcrumb 面包屑的使用方法

    Element Breadcrumb 面包屑的使用方法

    这篇文章主要介绍了Element Breadcrumb 面包屑的使用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07
  • Vue.js之$emit用法案例详解

    Vue.js之$emit用法案例详解

    这篇文章主要介绍了Vue.js之$emit用法案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-09-09
  • Vue实现插槽下渲染dom字符串的使用

    Vue实现插槽下渲染dom字符串的使用

    本文主要介绍了Vue实现插槽下渲染dom字符串的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • Vue生命周期实例分析总结

    Vue生命周期实例分析总结

    Vue的生命周期就是vue实例从创建到销毁的全过程,也就是new Vue()开始就是vue生命周期的开始。Vue实例有⼀个完整的⽣命周期,也就是从开始创建、初始化数据、编译模版、挂载Dom->渲染、更新->渲染、卸载等⼀系列过程,称这是Vue的⽣命周期
    2022-10-10

最新评论