A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© xiaofeifei112 中级黑马   /  2019-2-28 23:53  /  874 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

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 中和自身均含有相同属性时,混入属性值不会被添加到当前组件中。



0 个回复

您需要登录后才可以回帖 登录 | 加入黑马