一、背景:从"稳定"到"极致体验"
截至 2026 年,Vue 3.4 与 3.5 已全面普及,但许多能显著降低心智负担 的特性(如 defineModel)在早期被标记为"实验性",或仅在 3.5+ 才完全稳定。如果你还在写"Props + Emits"的样板代码来支持 v-model,或者被 ref 的命名耦合困扰,这部分内容正是为你准备的。
本教程聚焦于解决实际痛点的"新特性",而非基础 API。
二、defineModel:双向绑定的终极简化
1. 痛点背景
在 Vue 3.4 之前,实现一个支持 v-model 的组件需要大量样板代码:
- 声明
modelValueprop - 声明
update:modelValueemit - 手动触发事件
代码对比:实现一个 Input 组件
<!-- ❌ 旧写法(Vue 3.3及之前) -->
<script setup>
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
</script>
<template>
<input
:value="modelValue"
@input="emit('update:modelValue', $event.target.value)"
/>
</template>
<!-- ✅ 新写法(Vue 3.4+,defineModel) -->
<script setup>
// 一行搞定!自动处理 prop 和 emit
const model = defineModel()
</script>
<template>
<input v-model="model" />
</template>
父组件使用完全一致 :<MyInput v-model="message" />
2. 进阶用法
-
类型安全与默认值 :
const count = defineModel<number>({ default: 0, required: true }) -
多 v-model (如
v-model:title):const title = defineModel('title') const content = defineModel('content') -
修饰符处理 (如
v-model.trim):const [value, modifiers] = defineModel() if (modifiers.trim) { value.value = value.value.trim() }
三、useTemplateRef:解耦模板引用
1. 痛点背景
传统 ref 存在命名强耦合 问题:模板中的 ref="input" 必须与脚本中的变量名 const input = ref(null) 严格一致,且类型推断较弱。
2. 新方案
Vue 3.5 引入 useTemplateRef,通过 Key 建立联系,彻底解耦命名:
<script setup>
import { useTemplateRef, onMounted } from 'vue'
// 参数 "my-input" 对应模板中的 ref 属性
const el = useTemplateRef('my-input')
onMounted(() => {
el.value?.focus() // 完美类型推断(HTMLInputElement)
})
</script>
<template>
<input ref="my-input" /> <!-- 变量名与脚本解耦 -->
</template>
3. 核心优势
- 动态 Ref :轻松处理
v-for场景,通过动态 Key 获取元素。 - 组合式函数复用:可在 Hook 中直接使用,无需通过参数传递 ref。
四、响应式 Props 解构(Vue 3.5+)
1. 痛点背景
在 Vue 3.4 及之前,直接解构 defineProps 会丢失响应式 ,必须使用 toRefs 或一直带着 props. 前缀。
2. 新特性
Vue 3.5 编译器支持响应式解构,直接解构后仍保持响应式:
<script setup>
// ✅ Vue 3.5+:直接解构,响应式不丢失!
const { count = 0, title } = defineProps<{ count?: number, title: string }>()
// 可直接在 JS 和模板中使用 count、title
</script>
五、Watcher 增强与性能优化
1. 监听控制增强
Vue 3.5 为 watch 增加了精细控制能力:
const { pause, resume, stop } = watch(source, callback)
// 手动暂停/恢复监听(用于优化性能)
pause()
resume()
2. 深度监听优化
- 层级限制 :
{ deep: 2 }仅监听对象的前 2 层,避免全量深度监听的开销。 - 性能提升:底层重构后,大型对象的深度监听性能提升显著。
六、SSR 与工具类 API
1. useId:唯一 ID 生成
解决 SSR 环境下客户端与服务端 ID 不一致导致的水合错误:
<script setup>
const id = useId() // 生成唯一且稳定的 ID
</script>
<template>
<label :for="id">Label</label>
<input :id="id" type="text" />
</template>
2. defineOptions:定义组件选项
在 <script setup> 中直接定义组件名、继承属性等,无需额外 <script> 块:
<script setup>
defineOptions({
name: 'MyComponent',
inheritAttrs: false
})
</script>
七、升级与配置指南(2026版)
1. 版本要求
- Vue :
>= 3.4.0(defineModel稳定),>= 3.5.0(useTemplateRef、响应式解构) - TypeScript: 确保使用最新 Volar 插件以获得完整类型支持。
2. 构建配置(Vite)
若需在旧版开启实验性功能:
// vite.config.js
export default {
plugins: [
vue({
script: {
defineModel: true, // 显式开启(3.4 之前需要)
propsDestructure: true // 显式开启响应式解构(3.5 之前需要)
}
})
]
}
3. 最佳实践
- 新项目 :直接使用 Vue 3.5+,全面拥抱
defineModel和useTemplateRef。 - 老项目迁移 :优先替换频繁使用的
v-model组件和动态 ref 场景。
八、总结
Vue 3.4+ 的这些"新特性"并非颠覆性变革,而是对开发者体验的极致打磨。它们消除了大量样板代码,让逻辑更内聚,类型更安全。如果你已熟悉 Composition API,现在是时候升级工具链,用更优雅的方式编写 Vue 代码了。