有学有练才叫学习:学而不思则罔,思而不学则殆:学而不习,纸上谈兵,习而不进,画地为牢!

vue.mixin(如何在Vue 中管理 Mixins)搞懂这两点就足够了

vue 炮渣日记 2周前 (11-17) 15次浏览 已收录 0个评论 扫描二维码

前言

定义: mixin是为了让可复用的功能灵活的混入到当前组件中,混合的对象可以包含任意组件选项(生命周期,指令之类等等), mixin翻译过来叫混合,高级的词汇可以叫插件入侵

vue.mixin(如何在Vue 中管理 Mixins)搞懂这两点就足够了

简单使用

// 定义一个混合对象
const myMixin = {
  createdfunction () {
    this.hello()
  },
  methods: {
    hellofunction () {
      console.log('JS 每日一题')
    }
  }
}
// 定义一个使用混合对象的组件
const Component = Vue.extend({
  mixins: [myMixin]
})
var component = new Component() // JS 每日一题

选项合并(优先级)

当组件和混合对象含有同名选项时,选项会按照规则进行合并

代码理解

const mixin = {
  createdfunction () {
    console.log('混合对象的钩子被调用')
  }
}
new Vue({
  mixins: [mixin],
  createdfunction () {
    console.log('组件钩子被调用')
  }
})

// => "混合对象的钩子被调用"
// => "组件钩子被调用"
// 从上面的代码我们可以看出来混合对象的生命周期会被先调用

值为对象的选项,例如 methods, components 和 directives,将被混合为同一个对象。两个对象键名冲突时,取组件对象的键值对,Vue.extend() 也使用同样的策略进行合并。

代码理解

const mixin = {
  methods: {
    foofunction () {
      console.log('foo')
    },
    conflictingfunction () {
      console.log('from mixin')
    }
  }
}
const vm = new Vue({
  mixins: [mixin],
  methods: {
    barfunction () {
      console.log('bar')
    },
    conflictingfunction () {
      console.log('from self')
    }
  }
})
vm.foo() // => "foo"
vm.bar() // => "bar"
vm.conflicting() // => "from self"

全局混合

也可以全局注册混合对象。注意使用!一旦使用全局混合对象,将会影响到 所有 之后创建的 Vue 实例

// 为自定义的选项 'myOption' 注入一个处理器。
Vue.mixin({
  createdfunction () {
    var myOption = this.$options.myOption
    if (myOption) {
      console.log(myOption)
    }
  }
})
new Vue({
  myOption'hello!'
})
// => "hello!"

在了解了基本用法后再简单过一遍源码加深印象

// 源码地址 https://github.com/vuejs/vue/blob/52719ccab8fccffbdf497b96d3731dc86f04c1ce/src/core/util/options.js#L365

export function mergeOptions (
  parent: Object,
  child: Object,
  vm?: Component
): Object // flow语法,表明返回的是一个对象
  if (process.env.NODE_ENV !== 'production') {
    checkComponents(child)
  }

  if (typeof child === 'function') {
    child = child.options
  }

  normalizeProps(child, vm)
  normalizeInject(child, vm)
  normalizeDirectives(child)
  const extendsFrom = child.extends
  //若存在extends,则将其内容合并到父对象parent中保存,最后再和自身child合并
  if (extendsFrom) {
    parent = mergeOptions(parent, extendsFrom, vm)
  }
  // 若存在mixins,则将其内容合并到父对象parent中保存,最后再和自身child合并
  if (child.mixins) {
    for (let i = 0, l = child.mixins.length; i < l; i++) {
      parent = mergeOptions(parent, child.mixins[i], vm)
    }
  }
  
  //初始化一个对象,用于存储parent和child合并后的内容,并作为mergeOptions函数的结果返回
  const options = {}
  let key
  for (key in parent) {
    mergeField(key)
  }
  for (key in child) {
    if (!hasOwn(parent, key)) {
      mergeField(key)
    }
  }
  
  //使用策略对象对parent和child进行合并
  function mergeField (key{
    const strat = strats[key] || defaultStrat
    options[key] = strat(parent[key], child[key], vm, key)
  }
  return options
}

export function initMixin (Vue: GlobalAPI{
  Vue.mixin = function (mixin: Object{
    this.options = mergeOptions(this.options, mixin)
    return this
  }
}
喜欢 (0)
炮渣日记
关于作者:
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址