mixins先来看看官方介绍:
mixins 选项接受一个混入对象的数组。这些混入实例对象可以像正常的实例对象一样包含选项,他们将在 Vue.extend() 里最终选择使用相同的选项合并逻辑合并。举例:如果你的混入包含一个钩子而创建组件本身也有一个,两个函数将被调用
简单的理解就是Vue实例中的所有属性配置可以通过 mixins 实现继承。 [JavaScript] 纯文本查看 复制代码 var mixin = {
created: function () { console.log(1) }
}
var vm = new Vue({
created: function () { console.log(2) },
mixins: [mixin]
})
// => 1
// => 2
原理解析其实 mixins 用起来非常简单,但是其背后的原理,还是值得我们去深究的:
- 为什么 mixins 后,钩子函数是依次执行的,而不是替换?
- 为什么 mixins 后,自身 data 属性优于混入属性?
要想回答上面的问题,我们得从 vue 源码开始说起。
Vue 在初始化 mixin 的时候,对于不同的属性,采用的策略是不同的,初始化代码在文件 src/core/global-api.js 中, 如下:
[JavaScript] 纯文本查看 复制代码 import { mergeOptions } from '../util/index'
export function initMixin (Vue: GlobalAPI) {
Vue.mixin = function (mixin: Object) {
Vue.options = mergeOptions(Vue.options, mixin)
}
}
你会发现是通过 mergeOptions 函数来进行合并的,它在文件 src/core/util/options.js, 它的源码如下:
[JavaScript] 纯文本查看 复制代码 /**
* Merge two option objects into a new one.
* Core utility used in both instantiation and inheritance.
*/
export function mergeOptions (
parent: Object,
child: Object,
vm?: Component
): Object {
// 省略不必要代码
for (key in child) {
if (!hasOwn(parent, key)) {
mergeField(key)
}
}
function mergeField (key) {
const strat = strats[key] || defaultStrat
options[key] = strat(parent[key], child[key], vm, key)
}
return options
}
这个函数很好理解,大概做的事情就是将 child 的属性合入到 parent 中,不同属性采用了不同的策略,这些策略都定义在 strats 对象上。 我们先看看 生命周期函数 的合并策略,代码如下: [JavaScript] 纯文本查看 复制代码 /**
* Hooks and param attributes are merged as arrays.
*/
function mergeHook (
parentVal: ?Array<Function>,
childVal: ?Function | ?Array<Function>
): ?Array<Function> {
return childVal
? parentVal
? parentVal.concat(childVal)
: Array.isArray(childVal)
? childVal
: [childVal]
: parentVal
}
可以发现 Vue 实例的生命周期函数最终都赋值成了一个数组,并对 mixins 中的进行了数组合并。这就是为什么组件 mixins 后的生命周期函数是依次执行的原因。 同样再来看看 data 的合入策略: [JavaScript] 纯文本查看 复制代码 /**
* Helper that recursively merges two data objects together.
*/
function mergeData (to: Object, from: ?Object): Object {
let key, toVal, fromVal
for (key in from) {
toVal = to[key]
fromVal = from[key]
if (!hasOwn(to, key)) {
set(to, key, fromVal)
} else if (isObject(toVal) && isObject(fromVal)) {
mergeData(toVal, fromVal)
}
}
return to
}
这个过程就是对象属性的合并,但是 to 上的优先级是高于 from 的,这就是为什么我们在对一个组件进行 mixins 的时候,自身 data 优先级高于混入的 data 属性,也就是如果 mixins 中和自身均含有相同属性时,混入属性值不会被添加到当前组件中。
。
|