Vue Mixin 与 Composable 全解析(含源码对比)

604 阅读3分钟

一、Mixin 概念

Mixin 是一种复用组件逻辑的方式,本质是一个对象,可以包含组件的 datamethodscomputed、生命周期钩子等。

  • 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. 合并策略

类型选项说明
替换型propsmethodsinjectcomputed子选项覆盖父选项
合并型data递归合并对象属性
队列型生命周期钩子、watch组合为数组,正序执行
叠加型componentsdirectivesfilters利用原型链叠加,保留父级属性

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 优点

  1. 独立状态,每次调用生成新响应式数据
  2. 避免命名冲突
  3. 灵活组合多个功能逻辑
  4. 更易维护,符合 Vue 3 官方推荐

五、Vue 2 / Vue 3 Mixin 与 Composable 对比

特性Mixin (Vue 2/3)Composable (Vue 3)
类型对象函数
状态混入组件,可能覆盖独立状态,每次调用独立
命名冲突容易冲突避免冲突,解构使用
生命周期可含钩子setup 中调用,或使用生命周期钩子 API
可组合性强,可随意组合
官方推荐Vue 2 常用Vue 3 推荐

六、小结

  1. Mixin 仍然可用,但 Vue 3 官方推荐 Composable
  2. 源码核心mergeOptions 合并策略(替换、合并、队列、叠加)基本一致。
  3. 组合函数优势:逻辑复用、安全、灵活,可代替 Mixin。

理解源码和策略后,你可以更清楚 Mixin 的原理,同时在 Vue 3 项目中优先使用组合函数实现逻辑复用。


本文内容由人工智能生成,仅供学习与参考使用,请在实际应用中结合自身情况进行判断。