一、Mixin 概念
Mixin 是一种复用组件逻辑的方式,本质是一个对象,可以包含组件的 data、methods、computed、生命周期钩子等。
- Vue 2:通过
Vue.mixin()全局混入,或组件mixins局部混入。 - Vue 3:保留
mixins,但官方推荐使用 Composable(组合函数)实现逻辑复用。
局部混入示例
const myMixin = {
created() { console.log('mixin created') },
methods: { hello() { console.log('hello') } }
}
const CompA = {
mixins: [myMixin],
created() { console.log('CompA created') }
}
全局混入示例
Vue 2:
Vue.mixin({
created() { console.log('全局混入') }
})
Vue 3:
const app = createApp(App)
app.mixin({
created() { console.log('全局混入') }
})
app.mount('#app')
Vue 3 支持多应用实例,每个实例独立 Mixin。
二、Mixin 使用场景
主要用于 逻辑复用,例如多个组件都需要控制显示状态 isShowing:
const toggleMixin = {
data() { return { isShowing: false } },
methods: { toggleShow() { this.isShowing = !this.isShowing } }
}
const Modal = { template: '#modal', mixins: [toggleMixin] }
const Tooltip = { template: '#tooltip', mixins: [toggleMixin] }
这样可以减少重复代码,复用逻辑。
三、Vue 2 / Vue 3 源码解析
1. 全局 Mixin 源码
Vue 2 (/src/core/global-api/mixin.js):
export function initMixin(Vue) {
Vue.mixin = function(mixin) {
this.options = mergeOptions(this.options, mixin)
return this
}
}
Vue 3 (packages/runtime-core/src/apiMixin.ts):
export function mixin(app: App, mixin: ComponentOptions) {
app._context.mixins.push(mixin)
return app
}
核心都是将 Mixin 对象和组件选项进行合并,但 Vue 3 支持多实例,每个实例
_context保存 Mixin。
2. mergeOptions 方法(选项合并策略)
源码位置:/src/core/util/options.js
export function mergeOptions(parent, child, vm) {
if (child.mixins) {
child.mixins.forEach(m => parent = mergeOptions(parent, m, vm))
}
const options = {}
for (let key in parent) mergeField(key)
for (let key in child) if (!parent.hasOwnProperty(key)) mergeField(key)
function mergeField(key) {
const strat = strats[key] || defaultStrat
options[key] = strat(parent[key], child[key], vm, key)
}
return options
}
3. 合并策略
| 类型 | 选项 | 说明 |
|---|---|---|
| 替换型 | props、methods、inject、computed | 子选项覆盖父选项 |
| 合并型 | data | 递归合并对象属性 |
| 队列型 | 生命周期钩子、watch | 组合为数组,正序执行 |
| 叠加型 | components、directives、filters | 利用原型链叠加,保留父级属性 |
a. 替换型
strats.methods = function(parentVal, childVal) {
const ret = Object.create(null)
extend(ret, parentVal)
if (childVal) extend(ret, childVal)
return ret
}
b. 合并型(data)
function mergeData(to, from) {
if (!from) return to
Object.keys(from).forEach(key => {
if (!to.hasOwnProperty(key)) set(to, key, from[key])
else if (typeof to[key] === 'object' && typeof from[key] === 'object')
mergeData(to[key], from[key])
})
return to
}
c. 队列型(生命周期、watch)
function mergeHook(parentVal, childVal) {
return parentVal ? parentVal.concat(childVal) : Array.isArray(childVal) ? childVal : [childVal]
}
d. 叠加型(组件、指令、过滤器)
function mergeAssets(parentVal, childVal) {
const res = Object.create(parentVal || null)
if (childVal) Object.keys(childVal).forEach(key => res[key] = childVal[key])
return res
}
四、Composable(组合函数)概念
Vue 3 推荐使用 Composable 替代 Mixin:
// useToggle.js
import { ref } from 'vue'
export function useToggle(initial = false) {
const isShowing = ref(initial)
const toggleShow = () => { isShowing.value = !isShowing.value }
return { isShowing, toggleShow }
}
// Component.vue
import { useToggle } from './useToggle'
export default {
setup() {
const { isShowing, toggleShow } = useToggle()
return { isShowing, toggleShow }
}
}
Composable 优点
- 独立状态,每次调用生成新响应式数据
- 避免命名冲突
- 灵活组合多个功能逻辑
- 更易维护,符合 Vue 3 官方推荐
五、Vue 2 / Vue 3 Mixin 与 Composable 对比
| 特性 | Mixin (Vue 2/3) | Composable (Vue 3) |
|---|---|---|
| 类型 | 对象 | 函数 |
| 状态 | 混入组件,可能覆盖 | 独立状态,每次调用独立 |
| 命名冲突 | 容易冲突 | 避免冲突,解构使用 |
| 生命周期 | 可含钩子 | setup 中调用,或使用生命周期钩子 API |
| 可组合性 | 弱 | 强,可随意组合 |
| 官方推荐 | Vue 2 常用 | Vue 3 推荐 |
六、小结
- Mixin 仍然可用,但 Vue 3 官方推荐 Composable。
- 源码核心:
mergeOptions合并策略(替换、合并、队列、叠加)基本一致。 - 组合函数优势:逻辑复用、安全、灵活,可代替 Mixin。
理解源码和策略后,你可以更清楚 Mixin 的原理,同时在 Vue 3 项目中优先使用组合函数实现逻辑复用。
本文内容由人工智能生成,仅供学习与参考使用,请在实际应用中结合自身情况进行判断。