vue原理分析(九)研究new Vue()中的initLifecycle

在Vue.prototype._init 中有一些init函数,今天我们来研究这些init函数

Vue.prototype._init = function (options) {
  ......
  {
    initProxy(vm);
  }
  ......
  initLifecycle(vm);
  initEvents(vm);
  initRender(vm);
  callHook$1(vm, 'beforeCreate', undefined, false /* setContext */);
  initInjections(vm); // resolve injections before data/props
  initState(vm);
  initProvide(vm); // resolve provide after data/props
  callHook$1(vm, 'created');
  ......
}

上一篇中已经研究了initProxy,今天我们往下研究

Vue.prototype._init = function (options) {
  ......
  initLifecycle(vm);
  ......
}

看下源码 initLifecycle(vm);

function initLifecycle(vm) {
    const options = vm.$options;
    // locate first non-abstract parent
    let parent = options.parent;
    if (parent && !options.abstract) {
        while (parent.$options.abstract && parent.$parent) {
            parent = parent.$parent;
        }
        parent.$children.push(vm);
    }
    vm.$parent = parent;
    vm.$root = parent ? parent.$root : vm;
    vm.$children = [];
    vm.$refs = {};
    vm._provided = parent ? parent._provided : Object.create(null);
    vm._watcher = null;
    vm._inactive = null;
    vm._directInactive = false;
    vm._isMounted = false;
    vm._isDestroyed = false;
    vm._isBeingDestroyed = false;
}

这段函数

是给Vue实例上挂载了一些属性并设置了默认值,值得一提的是挂载$parent 属性和$root属性

vm.$parent = parent;
vm.$root = parent ? parent.$root : vm;

先看挂载$parent 属性

function initLifecycle(vm) {
  ......
  const options = vm.$options;
  // locate first non-abstract parent
  let parent = options.parent;
  if (parent && !options.abstract) {
      while (parent.$options.abstract && parent.$parent) {
          parent = parent.$parent;
      }
      parent.$children.push(vm);
  }
  vm.$parent = parent;
  ......
}

如果当前组件options有parent且当前组件不是抽象组件,就通过while循环来向上循环。直到符合条件,直到找到第一个不是抽象类型的父级时,将其赋值vm.$parent,同时把该实例自身添加进找到的父级的$children属性中。这样就确保了在子组件的$parent属性上能访问到父组件实例,在父组件的$children属性上也能访问子组件的实例。

接着是给实例上挂载$root属性,如下:

vm.$root = parent ? parent.$root : vm;

实例的$root属性表示当前实例的根实例,挂载该属性时,首先会判断如果当前实例存在父级,那么当前实例的根实例$root属性就是其父级的根实例$root属性,如果不存在,那么根实例$root属性就是它自己。这很好理解,举个例子:假如有一个人,他如果有父亲,那么他父亲的祖先肯定也是他的祖先,同理,他的儿子的祖先也肯定是他的祖先,我们不需要真正的一层一层的向上递归查找到他祖先本人,只需要知道他父亲的祖先是谁然后告诉他即可。如果他没有父亲,那说明他自己就是祖先,那么他后面的儿子、孙子的$root属性就是他自己了。

后续这个也很有意思

vm._provided = parent ? parent._provided : Object.create(null);

如果当前组件有parent父级,则把父级的_provided赋值给当前组件的_provided(父传子),以此实现provide传值

最后还将一些参数赋值false,实现生命周期的init

vm._isMounted = false;
vm._isDestroyed = false;
vm._isBeingDestroyed = false;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值