vue3.5 重要更新内容
解构 defineProps
在 Vue 3.5 之前,defineProps
不能直接解构。如果需要解构,可能会丢失响应式特性。而对于 props
的默认值,则需要配合 withDefaults
使用。
示例代码
父组件代码:
vue
<script setup>
import ChildComp from './ChildComp.vue';
</script>
<template>
<ChildComp></ChildComp>
</template>
子组件代码:
在 3.5 之前需要使用 withDefaults
:
vue
<script setup lang="ts">
import { defineProps, withDefaults } from 'vue'
withDefaults(defineProps<{
type?: 'card' | 'panel'
}>(), {
type: 'card'
})
</script>
<template>
<div>
<!-- 默认显示 card -->
{{ type }}
</div>
</template>
跳转到 Vue SFC Playground 查看效果。
在 3.5 之后,defineProps
支持直接解构,并且可以设置默认值:
vue
<script setup lang="ts">
import { defineProps } from 'vue'
const { type = 'panel' } = defineProps<{
type?: 'card' | 'panel'
}>()
// 这样是监听不到的
watch(type, () => {})
// 这样是可以监听到的
watch(() => type, () => {})
</script>
<template>
<div>
<!-- 默认显示 panel -->
{{ type }}
</div>
</template>
跳转到 Vue SFC Palyground 查看效果。
注意
但是通过解构的方式还有个弊端,就是使用 watch
的时候,需要传递一个 getter
才能够被监听。
useId
Vue 3.5 新增了 useId
方法,用于生成全局唯一的自增 ID。每个组件实例中生成的 ID 是独立的,不会重复。
使用示例
vue
<script setup>
import { useId } from 'vue'
const id = useId()
</script>
跨多个应用的唯一性
在同一个 createApp 实例中,useId 保证生成的 ID 是唯一的。如果需要在多个 createApp 实例中确保唯一性,可以通过设置 ID 前缀实现:
ts
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
app.config.idPrefix = 'app1-'
app.mount('#app')
useTemplateRef
在 Vue 3.5 之前,我们通过 ref
获取 DOM 或组件引用。缺点是:变量名必须与 ref
的值保持一致,且 ref
本身也只是为了声明响应式数据设计的。
传统方式
vue
<script setup lang="ts">
import { ref } from 'vue'
const buttonRef = ref<HTMLButtonElement | null>(null)
console.log(buttonRef.value)
</script>
<template>
<button ref="buttonRef"></button>
</template>
使用 useTemplateRef
Vue 3.5 提供了更灵活的 useTemplateRef
方法,允许自由命名引用变量:
vue
<script setup lang="ts">
import { useTemplateRef } from 'vue'
const buttonEl = useTemplateRef<HTMLButtonElement>('buttonRef')
console.log(buttonEl.value)
</script>
<template>
<button ref="buttonRef"></button>
</template>
onWatcherCleanup
在 watch
函数触发时,希望做一些清楚副作用的时候很有用,比如下面这样:
方式一
vue
<script setup>
import { watch, ref, onWatcherCleanup } from 'vue'
const num = ref(0)
watch(num, newVal => {
const handle = () => {
console.log('click', newVal)
}
window.addEventListener('click', handle)
// 在下次 watch 触发时调用
onWatcherCleanup(() => {
window.removeEventListener('click', handle)
})
})
</script>
方式二
vue
<script setup>
import { watch, ref } from 'vue'
const num = ref(0)
watch(num, (newVal, oldVal, onCleanup) => {
const handle = () => {
console.log('click', newVal)
}
window.addEventListener('click', handle)
// 在下次 watch 触发时调用
onCleanup(() => {
window.removeEventListener('click', handle)
})
})
</script>
隐藏功能:watch
在 Vue 3.5 中,watch
的深度监听新增了层级限制功能。通过设置 deep
的值,可以指定监听的对象层级深度。
示例代码
vue
<script setup>
import { watch, reactive } from 'vue'
const state = reactive({
a: {
b: {
c: 1
}
}
})
watch(
() => state,
() => {
console.log('watch')
},
{
deep: 2
}
)
</script>
watch
的其他隐藏功能看这里 watch的暂停、恢复、停止