vue mixin混入,生命周期执行阶段简易实现

全局混入生命周期,在vue中组件中,会收集都放在 Vue.options上,在组件上的混入的生命周期会收集在组件实列this.$options上

先实现将mixin中的生命周期函数收集到Vue.options,

形成这样的形势

全局mixin是给全部Vue文件添加一些公用的实例,我们需要实现一个Vue.mixin方法

来讲所有的全局注册的mixin里面的生命周期依次收集,我们这里只讲生命周期收集,像data,watch这些需要的自己添加策略去实现

    Vue.options = {}
Vue.mixin=function(option){
    let vmOption=this.options
    this.options=mergeOptions(vmOption,option)
    console.log('this.options',this.options)
}

先定义options,然后将用户写的mixin跟当前options上的生命周期进行合并

function mergeOptions (parent, child) {
//定义新的optins parent代表被合并的,child需要进行合并的
  let options = {}
//这里合并,情况分为,被合并上面有的parent,child上面可能有可能没有
  for (let key in parent) {
    mergeField(key)
    console.log(options)
  }
//还有种情况,上面已经遍历了parent上面的所有的属性,但是child上面有的,但是parent上面没有的情况还
// 没有遍历到,所有需要遍及child,然后排除parent上有的
  for (let key in child) {
    if (!parent?.hasOwnProperty(key)) {
      mergeField(key)
    }
  }
  function mergeField (key) {
    // 合并字段
    // 根据key 不同的策略来进行合并
    if (strats[key]) {
      options[key] = strats[key](parent[key], child[key])
    } else {
      // todo默认合并
      options[key] = child[key]
    }
  }
  return options
}

这里合并,情况分为,被合并上面有的parent,child上面可能有可能没有

//还有种情况,上面已经遍历了parent上面的所有的属性,但是child上面有的,但是parent上面没有的情况还
// 没有遍历到,所有需要遍及child,然后排除parent上有的

然后进行每一项的合并,在合并过程中我们需要用到策略模式

什么是策略模式呢?

策略模式的定义:定义一系列的算法,将他们一个个封装起来,使他们直接可以相互替换。

策略模式是开发中常用的第二种设计模式,它在开发中非常常见,由两部分组成。第一部分是策略类,封装了许多具体的,相似的算法。第二部分是环境类,接受客户请求,随后将请求委托给策略类。说的通俗一点就是将相同算法的函数存放在一个包装里边,每个函数用相同的方式拿出来,就叫做策略模式。

策略模式,可以帮助我们减少if else的写法

这里我们定义一个策略对象const strats = {}

我们需要合并到的生命周期方法合并的策略是一样的,但是在合并 data,watch computed,methods 是不一样的,所有我们需要写

strats.data=function (parent,child){}

strats.watch =function (parent,child){}

strats.computed=function (parent,child){}

每个的合并是不一样的,但是生命周期方法的合并是一样的,我们定义一个数组

const LIFECYCLE_HOOKS = [
  'beforeCreate',
  'created',
  'beforeMount',
  'mounted',
  'beforeUpdate',
  'updated',
  'beforeDestroy',
  'destroyed'
]

然后遍历数组,为生命周期定义合并方法

LIFECYCLE_HOOKS.forEach(key=>{
  strats[key]=mergeHook;
})
function mergeHook(parent,child){
  if(child){
    if(parent){
      return parent.concat(child)
    }else{
      return [child]
    }
  }else{
    return parent
  }
}

在mergeHook中,进行真正的合并,如果child中没有,直接返回parent ,

测试

 Vue.mixin({
        created: function () {
          var myOption = this.$options
          if (myOption) {
            console.log('1',myOption)
          }
        }
      })
      Vue.mixin({
        created: function () {
          var myOption = this.$options
          if (myOption) {
            console.log('2',myOption)
          }
        }
      })
      Vue.mixin({
        created: function () {
          var myOption = this.$options
          if (myOption) {
            console.log('3',myOption)
          }
        }
      })

在这里 parent 第一次代表的是  Vue.options = {},child代表的是

 第二次parent代表的是[created: function () {
          var myOption = this.$options
          if (myOption) {
            console.log('1',myOption)
          }
        }
      })],child代表的是

 最终打印出来 console.log('this.options',this.options)

结果

 在vue组件上的生命周期跟全局上的合并,是在vue初始化方法init里面Vue.prototype._init

Vue.prototype._init=function(option){
  let vm =this
  this.$options=option
  
  this.$options=mergeOptions(vm.constructor.options,option)
  
  console.log('this.$options',this.$options)
  //初始化:watch,computed props data 生命周期
  callHook(vm,'beforeCreate')
  initState(vm)
  callHook(vm,'created')
  if(option.el){
    vm.$mount(option.el)
  }
}

这里我们为什么用vm.constructor.options指向的是vue.options,为什么不直接用vue.options,却要用他的实列,大家可以思考一下

猜你喜欢

转载自blog.csdn.net/qq_27449993/article/details/127083301
今日推荐