Vue3.5正式上线,有哪些新特性和用法?

目录

前言

一、带响应式Props解构赋值

 二、Props默认值新写法

三、 useTemplateRef 函数

四、新增useId() 

 五、延迟传送(defer Teleport)

六、 新增 onWatcherCleanUp()


前言

Vue3.5 2024-09-03正式上线,目前在 Vue 官网显最新版本已经是 Vue3.5,其中主要包含了几个小改动,完整的过往发布记录可以在 GitHub 查阅。


一、带响应式 Props 解构赋值

简述:以前我们对 Props 直接进行解构赋值是会失去响应式的,需要配合使用 toRefs 或者 toRef 解构才会有响应式,那么就多了 toRefs 或者 toRef 这工序,而最新 Vue3.5 版本已经不需要了。

这样直接解构,testCount 能直接渲染显示,但会失去响应式,当我们修改 testCount 时页面不更新。

<template>
  <div>
    {{ testCount }}
   </div>
 </template>

<script setup>
 import { definProps } from 'vue';
 const props = definProps({
    testCount: {
      type: Number,
      default: 0,
     },
 });
</script>

保留响应式老式的写法,使用 toRefs 或者 toRef  解构

<template>
  <div>
    {{ testCount }}
  </div>
</template>

<script setup>
  import { definProps, toRefs, toRef } from 'vue';
  const props = definProps({
    testCount: {
      type: Nmuber,
      default: 0,
     },
  });

  const { testCount } = toRefs(props);
  //或者
  const testCount = toRef(props,'testCount')};
</script>

最新 Vue3.5 写法,依然保留响应式

<template>
  <div>
    {{ testCount }}
  </div>
</template>

<sceipt setup>
  import { definProps } from 'vue';
  const { testCount } = definProps({
   testCount {
    type: Number,
   },
});
</script>

相对以前便捷了,直接解构使用省去了  toRefs 或者 toRef 

 二、Props 默认值新写法

 简述: 以前默认值都是用 default: *** 去设置,现在不用了,现在只需要解构的时候直接设置默认值,不需要额外处理。

先看看旧的 default: *** 默认值写法

如下第12就是旧写法,其它以前 Vue2 也是这样设置默认值

<template>
  <div>
    {{ props.testCount }}
  </div>
</template>

<script setup>
  import { defineProps } from 'vue';
  const props = defineProps({
    testCount: {
      type: Number,
      default: 1
    },
  });
</script>

 最新优化的写法 如下第9行,解构的时候直接一步到位设置默认值,更接近js语法的写法。

<template>
  <div>
    {{ testCount }}
  </div>
</template>

<script setup>
  import { defineProps } from 'vue';
  const { testCount=18 } = defineProps({
    testCount: {
      type: Number,
    },
  });
</script>

三、 useTemplateRef 函数

 简述: unseTemplateRef 在之前获取 dom 节点需要给 dom 绑定上一个 ref='refKey',然后再用一个定义 ref 一个空的响应式属性赋值给这个 refKey ,如下所示:

<template>
  <div class="content" ref='myNode'>dom</div>
</template>

<script setup>
 import { ref, onMounted } from 'vue';
 const myNode = ref(null)
 onMounted(()=>{
   console.log(myNode)  //拿到 dom 节点
})
</script>

而现在,有了 unseTemplateRef 函数,我们可以更好的区分响应式属性和 dom 节点,不像之前响应式属性和 dom 节点都是通过 ref 和定义获取。

最新 Vue3.5 写法 unseTemplateRef 用法如下

<template>
 <span style="color: red" ref="myNode">是我</span>
</template>

<script setup>
 import { unseTemplateRef } from 'vue';
 const node = unseTemplateRef("myNode"); 
  //这里定义的接收 dom 节点的变量无需和 ref 一样,随意定义接收
 onMounted(()=>{
   console.log(node)    //拿到 dom 节点
})
</script>

四、新增 useId() 

 简述:useId() 是一个 API,用于生成在服务器和客户端渲染之间保持稳定的唯一应用程序 ID。这些 ID 可用于生成表单元素和无障碍属性的 ID。

<template>
  <el-form>
    <el-label :for="id">Name:</el-label>
    <el-input :id="id" type="text" />
  </el-form>
</template>

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

// 使用 useId 生成一个唯一的 id
 const id = useId()
</script>

 五、延迟传送(defer Teleport)

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

当使用 Teleport 组件时,指定的目标元素(即 to 属性所指向的选择器对应的元素)必须在页面的DOM(文档对象模型)结构中已经存在,否则 Teleport 就无法将内容传送过去。

比如,如果使用 <teleport to="#my-target">,但是页面中没有一个具有 id="my-target" 的元素,Teleport 就无法正常工作,因为找不到传送内容的目标位置。

代码如下:

<template>
  <div class="container">
   <Teleport defer to="#my-target">
     <p>传送内容...</p>
   </Teleport>
  </div>
 <div id="my-target"></div>
</template>

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

 Vue 3.5 中可以通过 defer 来延迟 Teleport 的挂载,它会等到同一更新周期中的所有其他 DOM 内容都渲染完毕后,再定位目标容器并挂在其子容器。

六、 新增 onWatcherCleanUp()

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

<template>
  <div>
    <el-button @click="id++">更改 ID </el-button>
    <p>当前 ID: {{ id }}</p>
  </div>
</template>

<script setup>
import { ref, watch, onWatcherCleanUp } form '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(() => {
// 如果 id 在请求完成之前发生更改,会取消之前的请求
  controller.abort();
 });
});
</script>

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

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

vue3.5 之前中也可以使用 onCleanup 函数作为第 3 个参数传递给 watch 函数:

watch(id, (newId, oldId, onCleanup) => {
  // ...
  onCleanup(() => {
    // 清除逻辑
  })
})

watchEffect((onCleanup) => {
  // ...
  onCleanup(() => {
    // 清除逻辑
  })
})


如果那里写的不对或者有更好建议欢迎大佬指点,感谢你们的关注以及点赞~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值