Vue的生命周期和钩子函数(一)——数据初始化

前言

了解Vue实例的创建过程,有助于帮助我们理解Vue内部的实现机制,更加深刻的理解钩子函数的作用和使用场景。本篇博文基于Vue2.X,3.0的一些特殊机制和语法暂不做考虑。阅读全篇时间约12分钟,仅了解钩子函数使用及使用场景,需约4分钟

正文

我们都知道,创建一个Vue实例,需要通过new Vue()来实现。那一个Vue实例创建到销毁的过程中,会存在哪些变化和会调用哪些功能呢?又会再什么场景下去触发钩子函数的调用呢,下面将通过讲述Vue实例的创建过程,来说明Vue的钩子函数的调用时机和场景。
一个Vue实例的生命周期,总体而言,可以划分为三个阶段:初始化阶段、数据响应阶段以及销毁阶段,我将通过多篇博文来介绍这几个阶段以及生命周期钩子函数的使用。

Vue实例初始化

一个正常简单的Vue实例化语句是下面这样的:

var vm  = new Vue({
	el:#app',
	data:{
		msg:'xxxx'
	}
})

我们通过调用Vue的构造函数来创建Vue实例,其中我们会传入一个对象,该对象包含了实例化Vue所需要的el、data等。在实例初始化阶段,Vue会根据传入的这个对象,去内部调用各种init()函数。期间Vue的四个生命周期的钩子函数也会被调用到,他们分别是:beforeCreate、created、beforeMount、Mounted,初始化的过程大致如下:
在这里插入图片描述
在我们正常的开发过程,只需要了解各个钩子函数的使用场景和前提就可以了,并不需要太去关注里面内部的实现机制,所以这里先说一下每个钩子函数的使用场景:

beforeCreate

beforeCreate钩子函数,如其名,是在Vue实例还未创建data、methods等之前,会触发调用的一个钩子函数,在触发这个函数的调用之前,Vue主要是做了一些简单的事件初始化等工作,比如emit,on,once,off等,平常开发中使用几率少。

created

created钩子函数,是在已经初始化好props、methods、data、computed、watch等之后,会去调用的钩子函数,但是此时属性el还没有被创建的,只是创建了实例的一些基本属性。created钩子函数中可以操作已经创建好的数据和方法,同时也可以调用异步的功能获取页面初始化所需的数据

beforeMount

在调用这个beforeMount之前,Vue已经编译好了模板并转化成了虚拟DOM,el也已经完成了对元素节点的挂载。在这个钩子函数里,我们可以修改data的数据并且不会触发updated和beforeUpdate钩子函数的调用,使用频率也较低。

mounted

mounted钩子函数是在虚拟DOM通过$el已经替换成为真实DOM树的之后被调用,此时页面中的html已经渲染完成,相对于created而言,如果需要去操作DOM树,那么可以放在mounted中去完成。此时也可以通过this.$ref去拿到ref绑定的元素节点。同时此时变更data的数据,会对应的触发updated和beforeUpdate钩子函数的调用。

说完了初始化阶段钩子函数的调用,现在我们来结合源码一起来解读下这个过程。下面这部分的内容涉及对源码的解读,没时间的小伙伴可以先收藏,后续再翻出来看看,加以理解
先来展示一段简单的实例化代码:

// 传入了一个包含el、data属性的对象来构建一个Vue实例
var vm = new Vue({
   
	el:'#app',
	data:{
   
		msg:''
	}
})

Vue实例的构建是通过new Vue()而来的,所以想要了解Vue实例化的过程,要先从它的构造函数Vue开始。

//代码路径:src\core\instance\index.js
function Vue (options) {
   
  if (process.env.NODE_ENV !== 'production' &&
    !(this instanceof Vue)
  ) {
   
    warn('Vue is a constructor and should be called with the `new` keyword')
  }
  this._init(options)
}

这里调用了一个_init函数,init函数主要如下:

// src\core\instance\init.js
// 省略部分代码
Vue.prototype._init = function (options?: Object) {
   
    const vm: Component = this
    ... 
    // Vue内部调用,正常不会走到这个分支
    if (options && options._isComponent) {
   
      initInternalComponent(vm, options)
    } else {
   
    // 使用策略对象合并参数选项合并父子组件的一些同名属性,包括指令、过滤器、钩子函数等,不同的合并对象采用不同的策略,这里不做深入
      vm.$options = mergeOptions(
        resolveConstructorOptions(vm.constructor),
        options || {
   },
        vm
      )
    }
    ...
    //初始化了一些内部属性和外部属性,比如外部属性:$children,$parent,$refs,$root等,内部属性_watcher等
    initLifecycle(vm) 
    //初始化父组件在模板中使用v-on或@注册的监听子组件内触发的事件。
    initEvents(vm)
    initRender
  • 8
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值