Vue源码分析–Vue.mixin
看源码,就是将mixin对象合并到this.options上
export function initMixin (Vue: GlobalAPI) {
Vue.mixin = function (mixin: Object) {
// 注意:这里的this.options不是指vm.$options, 而是Vue.options
// 初始为 Vue.options =
// {filters: {}, directives: {}, components: {KeepAlive}, _base: Vue}
this.options = mergeOptions(this.options, mixin)
return this
}
}
具体代码如下,这里删去了不重要的代码
export function mergeOptions (
parent: Object, // 父组件的options对象,这里指代 Vue.options
child: Object, // 将要合并的options对象,这里指代 mixin
vm?: Component
): Object {
// 检查child.components中的组件名key是否合法
checkComponents(child)
// 将props属性正规化,并特殊处理Array和Object类型
// options.props = ['str', 'my-foo']
// => options.props = {str: {type: null}, myFoo: {type: null}}
// options.props = {str1: String, str2: {type: String, required: true}}
// => {str1: {type: String}, str2: {type: String, required: true}}
normalizeProps(child, vm)
// 将inject属性正规化
// options,inject = ['key1', 'key2']
// => {key1: {from: 'key1'}, key2: {from: 'key2'}}
// options.inject = {key1: 'obj1', key2: obj2}
// => {key1: {from: 'obj1'}, key2: {from: 'key2', ...obj2}}
normalizeInject(child, vm)
// 将directives属性正规化
// options.directives = {my-dir: fn}
// => {my-dir: {bind: fn, update: fn}}
normalizeDirectives(child)
// 在生成构造函数Vue时,有这么一句 Vue.options._base = Vue
// 即child 不是Vue 或者Vue的子组件的options时,处理里面的内容
if (!child._base) {
// child.extends 对象可以看做是一个 mixin 对象
if (child.extends) {
parent = mergeOptions(parent, child.extends, vm)
}
// child.mixins = [options1, options2]
// mixins表示多个mixin,否则child表示mixin本身
if (child.mixins) {
for (let i = 0, l = child.mixins.length; i < l; i++) {
parent = mergeOptions(parent, child.mixins[i], vm)
}
}
}
const options = {}
let key
// 这里的parent === Vue.options ,并且合并了child.mixins与child.extend属性
// 初始值为 {filters: {}, directives: {}, components: {KeepAlive}, _base: Vue}
// 遍历parent中的属性,将parent[key]与child[key]一起合并到options中
for (key in parent) {
// 合并方式在下面
mergeField(key)
}
// 此时parent属性已合并完成,
// 并且(key in child) && (key in parent)的属性已处理完成
// 剩下的,将只在child中存在,parent中不存在的属性复制到options中
for (key in child) {
if (!hasOwn(parent, key)) {
mergeField(key)
}
}
// Function: 将parent[key]与child[key]一起合并到新对象options[key]上,分两种情况
// 1. 若key为内置属性(如:['data', 'props', 'methods', 'inject', 'computed', 'watch',
// 'provide', 'components', 'filters', 'directives', '生命周期'...]),进行特殊方式合并
// 2. 若key为非内置属性,用非空child[key]取代parent[key]
function mergeField (key) {
const strat = strats[key] || defaultStrat
options[key] = strat(parent[key], child[key], vm, key)
}
return options
}