Vue 3 组合式 API 香是香,但从Vue2迁移时你可别像我当初一样踩进这 3 个深坑里
是不是听说 Vue 3 组合式 API(Composition API)更好用了,逻辑复用好到飞起,Tree Shaking 瘦身效果一流,于是摩拳擦掌想把那个跑了两年的 Vue 2 老项目给升了?
打住!先听我讲个灵异事件。我之前把一个后台管理项目从选项式(Options API)往组合式硬切的时候,页面点着点着按钮不响应了,控制台一片寂静,我还以为我电脑坏了。最后查了俩小时——数据没加 .value 。
如果你不想经历这种“看着代码都对,跑起来全废”的绝望时刻,这篇文章就是为你准备的。咱们不念经,专门聊聊怎么带着老思维丝滑上车,以及我跪过的那些坑。
🎯 核心摘要:这 1200 字能帮你干点啥?
- 搞清楚组合式 API 和选项式 API 到底是不是“敌对关系”。
- 掌握一种渐进式迁移的偷懒大法,不用把旧代码全删了重写。
- 避开 3 个从 Vue 2 切过来最容易翻车的语法陷阱。
- 理解为什么官方非要搞出这套“新玩具”。
📖 第一部分:到底是升级还是折腾?
首先得给组合式 API 正个名。很多人觉得 Vue 3 是把 Vue 2 推翻了重来,其实不是。
你可以把选项式 API 想象成去餐厅吃套餐( data 是前菜,methods 是主菜,mounted 是甜点),虽然菜都给你配好了,但你要是想把隔壁桌的牛排和这边的沙拉混一起,得端着盘子跑来跑去(mixins 命名冲突、来源不明)。
组合式 API 呢?就像吃自助餐。你想拿什么拿什么,把拿来的东西全堆在一个大盘子里(setup 函数),一目了然。尤其是逻辑复用,以前 mixins 的痛,现在就是一个函数的事儿。
⚙️ 第二部分:核心原理,说人话版
好,咱们先来理解最核心的那层窗户纸。
选项式 API 是通过 this 上下文来访问数据的,这大家都熟。但组合式 API 没了 this,它靠的是闭包和响应式引用。
接下来重点来了,这也是我当初脑子转不过弯的地方:
ref 就像是给数据包了一层“带响应的壳”。
在 script 里你必须用 变量名.value 去戳它一下,它才搭理你;但在 template 模板里,Vue 偷偷帮你脱掉了这层壳,直接写变量名就行。
是不是以为这样就完了?
你可能会问:“那我以前的 data 里那么多对象,全改成 ref 不得累死?” 这时候就该 reactive 登场了。
它专门用来包对象,不用 .value,跟 Vue 2 的 data 手感最像。但注意,别对它解构,一解构响应性就飞了,这点后面会说。
💻 第三部分:实战演示与迁移偷懒指南
别一上来就想着把整个文件改成 setup 语法糖。官方给了个超级平滑的过渡方案,老项目里直接这么写:
<script>
import { ref } from 'vue';
export default {
// 你以前所有的 options 照写不误!data, methods, mounted 都留着
data() {
return { oldMsg: '我是老员工' };
},
// 直接在这里加一个 setup 函数,新逻辑写这里
setup() {
const newMsg = ref('我是新来的');
// 这里千万别学我当初偷懒,忘记 return 出去,模板里死活找不到变量
return { newMsg };
},
mounted() {
// 在选项式 API 里也能直接访问组合式暴露出来的变量!
console.log(this.newMsg);
}
};
</script>
看到了吗?你根本不用重构整个文件!新功能用组合式写,老功能保持原样。setup 里返回的东西会全自动混入 this,这招“新旧同居”简直是我等打工人的救星。
再说个容易翻车的点:在组合式里发请求替代 mounted。
以前我们都在 mounted 里写,现在没了 created/mounted 傻傻分不清的烦恼。在 setup 里直接写就行,它本身就介于 beforeCreate 和 created 之间。
但如果你非要等 DOM 挂载完,记得用 onMounted 钩子引入一下,别直接裸写。
⚠️ 第四部分:3 个让我加班到深夜的深坑
1. 解构 reactive 导致的“僵尸数据”
这个坑是我想把一个 reactive 对象里的 price 拿出来单独算折扣时踩的。
const state = reactive({ count: 0 });
const { count } = state; // ❌ 这么干 count 就变成普通数字 0 了,再也响应不了
解决方案:要么用 toRefs 把属性转成 ref,要么干脆用 ref 定义基本类型。
工具的选择好比选螺丝刀,不是最贵的就好,而是看你要拧十字还是一字。
2. Watch 监听 reactive 对象属性
你要监听 reactive 对象里的某个值,不能直接写属性名,得用一个 getter 函数包起来。
watch(() => state.count, (newVal) => { ... }) // ✅ 这才是对的
官方文档虽然这么说,但根据以往的经验,调整成这种函数形式传参会更稳,不会出现页面更新了但 watch 没反应的情况。
3. 忘记 .value 的灵魂暴击
用了 ref 之后,在 JS 里操作一定加 .value。
我现在已经形成肌肉记忆了,只要控制台报错说 xxx is not a function 或者没反应,第一反应就是查是不是落了 .value。
💡 总结与互动邀请
总结一下,组合式 API 真的挺好,特别是配合 TypeScript 和 Pinia 的时候,代码逻辑清晰得像看流程图。
别怕改变,也别急着推翻重来。先用我上面说的“新旧同居”模式慢慢切,遇到坑了回过头看看是不是我提到的这三个问题。
最后啰嗦一句:Vue 3 社区生态已经很成熟了,今年再不学,明年简历上写“精通 Vue”自己心里都得打个颤。
- 好了,茶水喝完,坑也帮你蹚平了 -
如果觉得有用,赶紧点个 收藏 和 关注,下次切 Vue 3 的时候翻出来对照着改,省得加班掉头发!
👇 评论区说说,你在切 Vue 3 时遇到的第一个报错是啥?
浙公网安备 33010602011771号