Vue mixin mixed in, easy implementation of life cycle execution phase

The global mix-in lifecycle, in the components in Vue, will be collected on Vue.options, and the mix-in lifecycle on the component will be collected on the component instance this.$options

First implement the collection of lifecycle functions in mixin to Vue.options,

form such a situation

Global mixin is to add some common instances to all Vue files, we need to implement a Vue.mixin method

Speaking of all the life cycles in the globally registered mixin are collected sequentially, we only talk about life cycle collection here, such as data, watch, etc. need to add strategies to achieve

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

Define options first, and then merge the mixin written by the user with the life cycle on the current 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
}

Merge here, the situation is divided into the parent that is merged, and the child may or may not be

//There is another situation, the above has traversed all the attributes on the parent, but there are some on the child, but there is no situation on the parent yet//It has not been
traversed, all need to traverse the child, and then exclude the ones on the parent

Then merge each item, we need to use the strategy mode in the merge process

What is the strategy pattern?

Definition of Strategy Pattern: Define a series of algorithms and encapsulate them one by one so that they can be directly replaced with each other.

Strategy pattern is the second design pattern commonly used in development, it is very common in development and consists of two parts. The first part is the strategy class, which encapsulates many specific and similar algorithms. The second part is the environment class, which accepts client requests and then delegates the request to the policy class. To put it more simply, the functions of the same algorithm are stored in a package, and each function is taken out in the same way, which is called the strategy mode.

Strategy mode can help us reduce the writing of if else

Here we define a strategy object const strats = {}

The strategy of merging the lifecycle methods we need to merge into is the same, but the merging of data, watch computed, and methods is different, so we need to write

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

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

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

The merging of each is different, but the merging of life cycle methods is the same, we define an array

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

Then iterate over the array, defining the merge method for the life cycle

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
  }
}

In the mergeHook, do the real merge, if not in the child, return directly to the parent,

test

 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)
          }
        }
      })

Here parent represents Vue.options = {} for the first time, and child represents

 The second parent represents [created: function () {           var myOption = this.$options           if (myOption) {             console.log('1',myOption)           }         }       })], child represents





 Finally print out console.log('this.options',this.options)

result

 The life cycle on the vue component is merged with the global one, which is Vue.prototype._init in the vue initialization method 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)
  }
}

Here why do we use vm.constructor.options to point to vue.options, why not use vue.options directly, but use its real column, you can think about it

Guess you like

Origin blog.csdn.net/qq_27449993/article/details/127083301