人人都能懂的Vue源码系列(六)—initLifecycle

本文深入解析Vue.js中initLifecycle方法的实现细节,介绍如何初始化组件的生命周期相关属性,并解释父组件与子组件间的关系建立过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上篇文章中,我们主要讲了initProxy相关的内容。它主要是通过Proxy为vm对象代理一些自定义的行为。今天我们回到init方法中,继续为大家讲解initLifecycle方法。 initLifeCycle方法主要用来初始化生命周期相关的属性,以及为parent,child属性赋值,先来看源码。

export function initLifecycle (vm: Component) {
  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._watcher = null
  vm._inactive = null
  vm._directInactive = false
  vm._isMounted = false
  vm._isDestroyed = false
  vm._isBeingDestroyed = false
}
复制代码

我们一行一行来分析

const options = vm.$options
复制代码

把mergeOptions后的options赋值给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)
  }
复制代码

我们注意到,vue作者对这段代码提供了一行注释

locate first non-abstract parent

定位第一个"非抽象"的父组件,注意非抽象这三个字。什么是非抽象呢?最初自己也很疑惑,最后在vue文档中找到了答案。

抽象组件的定义如上图所示,注意这句话,不会出现在父组件链中。明白了这点之后再去看上面的代码就不会那么迷惑了。

let parent = options.parent
if (parent && !options.abstract) {
    ... 
}
复制代码

如果当前vm实例存在父实例,则把父实例赋值给parent变量。当父实例存在,且该实例不是抽象组件,则执行下面代码

while (parent.$options.abstract && parent.$parent) {
  parent = parent.$parent
}
parent.$children.push(vm)
复制代码

注意while循环内的条件parent.$options.abstract && parent.$parent,如果父实例parent是抽象组件,则继续找parent上的parent,直到找到非抽象组件为止。

之后把当前vm实例push到定位的第一个非抽象parent的$children属性上,现在我们知道了怎么匹配vm实例上的parent属性。之后回到initLifecycle继续往下看

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

  vm.$children = []
  vm.$refs = {}
  vm._watcher = null
  vm._inactive = null
  vm._directInactive = false
  vm._isMounted = false
  vm._isDestroyed = false
  vm._isBeingDestroyed = false
复制代码

这部分代码是为vm上的一些属性赋值,这些属性的作用如下表。

名称说明
$parent指定已创建的实例之父实例,在两者之间建立父子关系。子实例可以用 this.parent 访问父实例,子实例被推入父实例的children 数组中。
$root当前组件树的根 Vue 实例。如果当前实例没有父实例,此实例将会是其自己。
$children当前实例的直接子组件。需要注意 $children 并不保证顺序,也不是响应式的。
$refs一个对象,持有已注册过 ref 的所有子组件。
_watcher组件实例相应的 watcher 实例对象。
_inactive表示keep-alive中组件状态,如被激活,该值为false,反之为true。
_directInactive也是表示keep-alive中组件状态的属性。
_isMounted当前实例是否完成挂载(对应生命周期图示中的mounted)。
_isDestroyed当前实例是否已经被销毁(对应生命周期图示中的destroyed)。
_isBeingDestroyed当前实例是否正在被销毁,还没有销毁完成(介于生命周期图示中deforeDestroy和destroyed之间)。

initLifecycle方法的逻辑比较简单,主要对vue实例上一些属性进行赋值。所以这里就不画流程图来进行说明了。下篇文章我们主要讲initEvents方法,敬请期待。

最后在这里说一句,我们这套vue源码解读文章,基本上可以说是全网讲的最详细的了,基本做到了讲解每行代码的意义。这也花费了作者大量的精力和业余时间,如果大家喜欢我的文章,请不要吝惜你们的点赞和关注。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值