API 香是香,但从Vue2迁移时你可别像我当初一样踩进这 3 个深坑里 - 搞清楚组合式 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。 总结与互动邀请