Vue源码之mixin

1,496 阅读3分钟

合并配置流程 mixin

调用Vue.mixin做了啥

在initGlobalAPI(Vue)时会初始化mixin调用initMixin(Vue)然后在 src/core/global-api/mixin.js 中可以看到mixin的定义:

可以看到此时是往全局options也就是Vue.options中扩展我们传入的内容东西。

初始化时自定义options合并

在初始化时自定义options合并 src/core/instance/init.js

初始化组件时 组件options合并

这里就是将Vue.options和组件定义的options合并成组件的options。

mergeOptions

在src/core/util/options.js中,mergeOptions 主要功能就是把 parent 和 child 这两个对象根据⼀些合并策略,合并成⼀个新对象并返回。⽐较核⼼的⼏步,先递归把 extends 和 mixixns 合并到 parent 上,然后遍历parent ,调⽤ mergeField ,然后再遍历 child ,如果 key 不在 perent 的⾃⾝属性上,则调⽤ mergeField 。mergeField 函数它对不同的 key 有着不同的合并策略。

几种合并策略方式

其中created、mounted等生命周期钩子函数,mixins的函数和组件中的都会被执行,且mixins中的会被先执行。
components、methods 、computed、data为值对象。当遇到值对象属性冲突(对象键名相同)时,组件选项优先 ,组件选项覆盖。

data provide合并

把两个函数合并加到一个新函数中,并返回这个函数,冲突组件选项覆盖。

静态资源合并

原型叠加,两个对象并没有进行遍历合并,而是把一个对象直接当做另一个对象的原型,这种做法的好处,就是为了保留两个相同的字段且能访问,避免被覆盖。

watch合并

watch 的处理,是合并成数组,重要的也是合并顺序,最终按照生成是数组进行执行。

props methods inject computed

这几个东西,是不允许重名的,合并成对象的时候,不是你死就是我活,重要的是,以谁的为主?必然是组件options 为主了

生命周期合并

这⾥定义了 Vue.js 所有的生命周期钩⼦函数名称,所以对于钩⼦函数他们的合并策略都是 mergeHook 函数。这个函数的实现也⾮常有意思,⽤了⼀个多层 3 元运算符,逻辑就是如果不存在 childVal ,就返回 parentVal ;否则再判断是否存在 parentVal ,如果存在就把 childVal 添加到parentVal 后返回新数组;否则返回 childVal 的数组。所以回到 mergeOptions 函数,⼀旦parent 和 child 都定义了相同的钩⼦函数,那么它们会把 2 个钩⼦函数合并成⼀个数组。最后执行顺序就是按这个数组的顺序执行的。

举个栗子

  • 两处断点
  • 第一个断点进入Vue.mixin把钩子合并到Vue的options中
  • 进入mergeOptions
  • 进入mergeHook
  • 第二个断点进入new Vue
  • 进入mergeOptions
  • 然后进入创建子组件构造函数时
  • 进入mergeOptions
  • 然后执行子组件初始化init
  • 最后子组件vm.$options

总结