Vue 3 编程的 10 个实用技巧
(2025-2026 年后端转前端 / 中高级开发者最常使用的写法)
以下 10 个技巧几乎覆盖了目前绝大部分中大型 Vue 3 项目中最实用、最能提升代码质量和开发效率的部分,按“日常使用频率”从高到低排序。
| 排名 | 技巧名称 | 实用程度 | 节省时间 | 推荐掌握程度 | 主要解决的问题 |
|---|---|---|---|---|---|
| 1 | 组合式 API 的正确拆分与组织 | ★★★★★ | ★★★★★ | 必须精通 | 组件逻辑太长、难以复用 |
| 2 | 使用 toRefs 解构 reactive 对象 | ★★★★★ | ★★★★☆ | 强烈推荐 | 解构后丢失响应式 |
| 3 | 正确使用 shallowRef / shallowReactive | ★★★★☆ | ★★★★☆ | 性能敏感必备 | 大对象频繁更新导致性能爆炸 |
| 4 | computed + watch 的正确使用边界 | ★★★★☆ | ★★★★☆ | 必须掌握 | 避免无限循环 & 重复计算 |
| 5 | 组件通信:defineEmits + defineExpose | ★★★★☆ | ★★★★☆ | 强烈推荐 | 替代 this.$emit / this.$refs |
| 6 | 优雅处理异步 setup(Suspense + async setup) | ★★★☆☆ | ★★★★☆ | 中大型项目必备 | loading 状态管理 |
| 7 | 使用 markRaw 解决第三方库响应式问题 | ★★★☆☆ | ★★★☆☆ | 常见坑 | 第三方库对象被错误代理 |
| 8 | v-model 自定义组件的最新写法 | ★★★★☆ | ★★★★☆ | 表单组件必备 | 统一组件双向绑定接口 |
| 9 | provide/inject + 依赖注入最佳实践 | ★★★☆☆ | ★★★☆☆ | 中大型项目 | 深层组件传参地狱 |
| 10 | 合理使用 <script setup> 之外的选项式 API | ★★★☆☆ | ★★★☆☆ | 过渡/遗留 | 兼容旧思维 & 特殊场景 |
10 大实用技巧代码示例(精简版)
- 组合式 API 推荐拆分方式(2025-2026 最流行写法)
// useUser.ts
export function useUser() {
const user = ref({ name: '', age: 0 })
const isAdult = computed(() => user.value.age >= 18)
const fetchUser = async () => {
// ...
}
return {
user,
isAdult,
fetchUser
}
}
// 使用
const { user, isAdult, fetchUser } = useUser()
- toRefs 正确用法(最常犯错点)
const state = reactive({ count: 0, name: '张三' })
// ❌ 这样写会丢失响应式
// const { count, name } = state
// ✅ 推荐写法
const { count, name } = toRefs(state)
- shallowRef/shallowReactive 性能优化
// 大型配置对象只希望顶层响应式
const config = shallowReactive({
theme: 'dark',
// 下面这棵大树不需要深层响应
menuTree: veryLargeMenuTreeObject
})
- computed + watch 正确边界
// 推荐:能用 computed 就尽量用 computed
const fullName = computed(() => `${firstName.value} ${lastName.value}`)
// 必须用 watch 的场景
watch(() => someComplexCondition.value, (newVal) => {
if (newVal) doHeavyTask()
}, { immediate: true })
- defineEmits 的类型安全写法(强烈推荐)
const emit = defineEmits<{
(e: 'update', value: string): void
(e: 'delete', id: number): void
}>()
// 这样写有类型提示和错误检查
emit('update', 'new value')
- Suspense + async setup(优雅 loading)
<script setup lang="ts">
const data = ref(null)
const { pending } = await useAsyncData(async () => {
data.value = await fetchUserProfile()
})
</script>
<template>
<Suspense>
<template #default>
<!-- 内容 -->
</template>
<template #fallback>
<div class="loading">加载中...</div>
</template>
</Suspense>
</template>
- v-model 自定义组件最新写法(Vue 3.3+ 推荐)
// MyInput.vue
<script setup>
const modelValue = defineModel<string>({ required: true })
</script>
<template>
<input v-model="modelValue" />
</template>
- markRaw 解决常见第三方库问题
import { markRaw } from 'vue'
import SomeThirdLib from 'some-lib'
const instance = markRaw(new SomeThirdLib()) // 防止被代理
- provide/inject 最佳实践(类型安全)
// types.ts
interface UserInfo {
name: string
role: string
}
const UserSymbol = Symbol() as InjectionKey<UserInfo>
// 提供
provide(UserSymbol, { name: '管理员', role: 'admin' })
// 注入
const user = inject(UserSymbol)!
- 合理混用
<script setup>与 Options API
<script lang="ts">
export default {
name: 'MyComponent', // 必须用 Options 才能定义 name
inheritAttrs: false // 常见需要关闭的情况
}
</script>
<script setup lang="ts">
// 组合式 API 部分
const props = defineProps<{ msg: string }>()
</script>
2026 年最真实的一句话总结:
“你写 Vue 3 的水平高低,其实就看你对组合式 API 的拆分能力、响应式边界把握能力、以及类型安全意识这三件事做得怎么样。”
如果你能把上面 10 条里 ★★★★★ 和 ★★★★☆ 的部分全部吃透,写出来的 Vue 3 代码基本已经达到中高级水准了。
你目前在 Vue 3 项目里最常遇到、让你最头疼的写法问题是什么?
(比如组合式 API 拆分困难、响应式丢失、类型报错、watch 乱用等等)
告诉我,我可以给你更针对性的解决方案和代码模板~