在 Vue 3 的项目迭代中,逻辑复用始终是组件设计的核心难题。当多个页面都需要相同的用户权限判断或接口轮询逻辑时,如果仍沿用旧思路,代码很容易变得零散且难以追踪。Vue 3 提供了 Composition API 与 Options API 两套写法,它们在组织可复用逻辑时的心智模型完全不同,直接影响后期重构效率。

Options API 的逻辑复用机制与局限
Options API 是 Vue 2 延续下来的经典写法,开发者通过在组件对象中声明 data、methods、computed 等选项来组织代码。在逻辑复用方面,最常见的手段是 mixins 和 extends。mixins 允许把一组选项原样混入多个组件,看似解决了重复代码问题,但实际上隐藏了不少隐患。
当项目复杂度上升,一个组件可能引入三四个 mixins,这时会出现属性来源不清晰的问题。你很难直观知道 this.refresh() 到底定义在哪个 mixins 里。更麻烦的是命名冲突:如果两个 mixins 都声明了 loading 数据,后混入的会覆盖前面的,且编译器不会给出明确警告。在调试时,这种隐性覆盖常常耗费大量时间。
下面是一段使用 mixins 实现鼠标位置追踪的示例,逻辑被拆到外部文件,组件内无法直接看出完整数据流:
// mouseMixin.js
export const mouseMixin = {
data() {
return { x: 0, y: 0 }
},
mounted() {
window.addEventListener('mousemove', this.updatePos)
},
methods: {
updatePos(e) {
this.x = e.clientX
this.y = e.clientY
}
}
}
// MyComponent.vue
import { mouseMixin } from './mouseMixin'
export default {
mixins: [mouseMixin],
template: '<div>{{ x }}, {{ y }}</div>'
}
从上面的代码可以看到,组件模板里的 x 和 y 并不在自身选项中声明,而是由 mixins 注入。对于新接手项目的同事,必须翻看所有混入文件才能理解组件行为,这明显提高了认知负担。
Composition API 的封装思路与优势
Composition API 以 setup 函数为入口,鼓励把相关联的响应式状态、计算属性和方法写成一个独立的组合函数(composable)。这种函数通常返回普通对象或响应式引用,组件内通过解构即可使用,来源一目了然。逻辑复用不再依赖选项合并,而是像调用普通 JavaScript 函数一样自然。
同样以鼠标位置为例,用 Composition API 可以改写成如下形式。逻辑完全内聚在一个文件,且返回值命名由调用方决定,从根源上避免了冲突:
// useMouse.js
import { ref, onMounted, onUnmounted } from 'vue'
export function useMouse() {
const x = ref(0)
const y = ref(0)
function updatePos(e) {
x.value = e.clientX
y.value = e.clientY
}
onMounted(() => window.addEventListener('mousemove', updatePos))
onUnmounted(() => window.removeEventListener('mousemove', updatePos))
return { x, y }
}
// MyComponent.vue
import { useMouse } from './useMouse'
import { ref } from 'vue'
export default {
setup() {
const { x, y } = useMouse()
const title = ref('鼠标追踪')
return { x, y, title }
},
template: '<div>{{ title }}: {{ x }}, {{ y }}</div>'
}
这段代码中,useMouse 就是一个标准的组合函数。它内部自己管理生命周期钩子,对外只暴露需要的响应式变量。因为返回时用了解构赋值,即使不同组合函数都返回叫 x 的变量,调用方也可以重命名为 mouseX 来规避冲突。同时,由于本质是函数调用,在单元测试中直接引入 useMouse 就能跑通逻辑,不需要挂载完整组件。
类型推导也是 Composition API 的强项。在 TypeScript 项目里,组合函数返回的对象类型可以被精确推断,IDE 能直接提示 x.value 是数字。而 Options API 的 mixins 由于是运行时合并,很多编辑器无法识别混入后的属性类型,只能靠开发者自己记忆。
重构旧项目时的渐进式迁移策略
对于存量 Vue 2 或早期 Vue 3 项目,一次性把所有组件改为 Composition API 并不现实。更稳妥的做法是在 Options API 组件中通过 setup 选项逐步引入组合函数。Vue 3 允许在同一个组件里既写 data 又写 setup,两者可以通过 this 与返回对象互相访问,这为平滑重构提供了基础。
具体实施时,可以先挑出复用频率最高、最易出 bug 的 mixins,比如用户信息和权限判断,将其改写成 useUser 之类的组合函数。然后在原组件里保留 Options API 结构,仅在 setup 中调用该函数并把结果透传给模板。这样既不打乱原有业务,又让核心逻辑率先获得更好的可测试性。
export default {
data() {
return { localCount: 0 }
},
setup() {
const { userName, isAdmin } = useUser()
return { userName, isAdmin }
},
computed: {
display() {
return this.localCount + ' - ' + this.userName
}
}
}
当团队熟悉组合函数写法后,再对新组件统一采用 <script setup> 语法,彻底告别 mixins。需要注意,如果老组件依赖大量 this.$refs 或第三方指令,迁移时要确认这些特性在 setup 上下文中的替代方案,避免重构引入新故障。总体而言,Composition API 并非要完全否定 Options API,而是提供更细粒度的逻辑复用能力,让重构路径更可控。
Vue3Composition_APIOptions_API修改时间:2026-08-18 18:16:42