关键在于使用 Vue Demi 作为标准化抽象层,它根据 Vue 版本自动桥接 Composition API 实现,统一 ref、reactive 等 API 行为,并需规避底层差异如 reactive 对象相等性、数组追踪及动态属性添加方式。

要让 Vue 响应式 API(如 ref、reactive、computed)在 Vue 2 和 Vue 3 中表现一致,不能靠手动适配或条件判断写两套逻辑,关键在于借助标准化的抽象层——核心是 Vue Demi。
用 Vue Demi 统一 API 入口
Vue Demi 不是 polyfill,而是编译期智能桥接工具。它根据项目实际安装的 Vue 版本,自动映射正确的底层实现:
- 若项目使用 Vue 2.6 及以下,它会自动引入并代理
@vue/composition-api插件提供的 API - 若为 Vue 2.7,直接使用其内置的 Composition API(注意:响应式机制仍是
Object.defineProperty) - 若为 Vue 3.x,则挂载原生 Proxy 实现的响应式系统
- 所有导出(
ref、computed、onMounted等)保持签名与行为高度一致,开发者无需感知版本差异
避开版本特有陷阱
即使用了 Vue Demi,某些行为仍因底层机制不同而存在隐性差异,需主动规避:
使用 JSON Schema 验证 JSON 数据,从示例 JSON 生成 schema,并将其转换为 TypeScript 接口、Python 数据类或 Markdown 文档。
-
reactive({}) === {}在 Vue 2.7 中为true,Vue 3 中为false;建议统一用ref包裹对象,或始终通过toRefs解构使用 - 数组作为
reactive的根值在 Vue 2.7 中不被追踪(会警告),应改用ref([]) - 动态新增属性:Vue 2.7 仍需
Vue.set或this.$set(尽管 Composition API 可用),而 Vue 3 直接赋值即可;若需跨版本通用,可用set(Demi 已重导出)封装一层 -
readonly在 Vue 2.7 中不拦截新增属性和数组操作,敏感场景建议配合Object.freeze或运行时校验
构建时确保环境一致性
开发和构建阶段的配置直接影响 API 行为是否对齐:
立即学习“前端免费学习笔记(深入)”;
- 在
package.json中声明严格的 peer 依赖:"peerDependencies": {"vue": "^2.7.0 || ^3.0.0"},避免混用 2.6 和 3.x - 组件库发布前,用 Vue Demi 提供的
isVue2/isVue3做最小必要分支(例如仅在 Vue 2 中补全onActivated的兼容逻辑),而非整个响应式逻辑 - ESLint 规则应启用
eslint-plugin-vue的vue/valid-definition-order和vue/require-explicit-emits,提前捕获 Vue 2.7 不支持的语法(如顶层await)
测试覆盖真实运行时行为
单元测试不能只跑在单一 Vue 版本下:
- 用
vitest或jest搭配@vue/test-utils,分别在 Vue 2.7 和 Vue 3 环境中执行同一套测试用例 - 重点验证:响应式数据修改后,
watch是否触发、computed是否重新求值、模板中插值是否更新 - 对数组操作(如
arr[0] = 'new'、arr.length = 0)单独写断言,Vue 2.7 需显式调用Vue.set才生效,而 Vue 3 不需要

















