vue 通过el-radio 调用mounted_从源码中学Vue(一)生命周期中的钩子函数的那点事儿...

欢迎来到我的《从源码中学Vue》专题系列文章,更多精彩内容持续更新中,欢迎关注 :)

466582039d1e7f8663c4c9cb315b182f.png

Vue作为当下前端最流行的框架之一,在国内占绝对的优势。所以接下来我们一起来学习它吧!

我不会像其它人一样去教大家怎么去使用vue的API,那些官网有详细的教程,而我将带着大家一起进入它的源码看看vue究竟做了什么?

所以,接下来我希望正在阅读的你具有以下基础

  1. 较好的JS基本功。
  2. 有JS面向对象基础,不清楚的可以去看下我上一个专题——《JS从入门到不放弃》里面有我对面向对象的理解。
  3. 有一定的Vue基础

废话不多说,直接开始

本章目标

  1. 如何去阅读vue的源码
  2. 从源码去看vue的生命周期
  3. 钩子函数的执行顺序

如何去阅读vue的源码

对于很多人来说,初识vue都是通过官网或者cdn网站下载vue.js文件。我们接下来要分析的源代码并不这个vue.js文件。

这个文件是经过编译后的文件,想要从这里面分析源码是比较困难的,所以我分析的源代码是通过yarn 安装到node_modules里面的vue。

我们先来实现一个简单的vue示例。

e95e545e17d6512bac93f032183a5836.png

一个最简单的vue示例

从这段代码可以看出来。在全局作用域下有一个Vue的类。好,这样我们去找Vue的源码。

在node_modules里面找到vue模块,展开看看里面的目录结构,它长这样

feeb41c8ba8952e6de44968dc759f958.png

从源码去看vue的生命周期

Vue这个类的定义我已经找出来了,它在vue/src/core/instance/index.js下。来看它里面都有什么?

2b11e2f3a1bc0d410bda3685479b733c.png

很容易就找到了Vue的全局定义,可以看出来,它是通过ES5的function 来模拟类的。然后里面有一个判断是这样的

if (process.env.NODE_ENV !== 'production' && !(this instanceof Vue) ) { warn('Vue is a constructor and should be called with the `new` keyword') }

我们就只看这一坨代码

 !(this instanceof Vue)//有面向对象基础的童鞋一下子就明白了,当前的this对象必须是Vue的一个实例,换句话说,我们只能够通过new Vue()去启动vue程序。而不能通过vue()这样。

为了验证我说的,试一把。

79e0af195a20136553bca9307eed0e74.gif

可以看到,那个标红的提示就是warn里面的提示。

继续往下看。

9eb31df98cea17e020b61c0d535dbae5.png

就直接调用了一个this._init()方法。

但是这个_init方法在哪定义的呢??

再往下看,

f8196a5f0b9d6ef09392acdc65cff7b1.png

有这么多方法。通过init,我们找第一个initMixin即可。

import { initMixin } from './init'

这个方法的定义就在当前目录下的init.js中,去这个文件看看里面有什么?

79729b7d782c8dc8b05de588b68b1d6a.png

注意:vue方法的参数中带有类型,这是typescript的写法,我们可以直接

我们找到了initMixin方法的定义。有些代码不用看,往下走,在第55行会找到这一坨代码

9377471c88fa619fc063eda4fad11406.png

好像找到了我们的生命周期的函数的影子。我们再去找callHook的方法的定义。

callHook,从字面上理解,它的意思是就调用钩子函数

2af27531c6454fd83f19e84cc6baac4c.png

再进去找到lifecycle.js,找到callHook的定义。

d32d2826c3f3b0399c7f7025e47d2646.png

这里面的第二个参数是我们的生命周期函数的名字。比如,beforeCreate,created等

我们再往里面找invokeWithErrorHandling函数。

7372fed63c3ca26a53336bbbdc2b850d.png

它在核心模块下的util目录下的index.js

4a70d5e22777e52734aa12601de2ee85.png

找到这样的一坨代码,额,好吧,invokeWithErrorHandling这个方法里面有一个error,所以我会先去找到error.js文件。

a56f05d156b5683e325f1d1a553f2956.png

找到了这最终的调用位置。invokeWithErrorHandling从字面上理解就是通过带有异常处理的函数。

再来看我圈出来的代码。这一块就是最终调用的生命周期钩子函数。注意看,最终调用handler的时候使用了call改变了钩子函数的this指向。

我们在调用invokeWithErrorHandling的时候,第二个参数传的是vm也就是我们的vue实例。

所以我们在钩子函数中,可以使用this去访问vm对象下的数据。

接下来我们来验证一下

1ae6c019c61937f240a0ea3aa2d50534.gif

看得出来,vue已经将钩子函数中的this指向了Vue对象。

如果没有调用call我们来看下默认的this指向什么?我来写一个简单的示例。

998f21e2ae62a8e1d246730de0a4de07.gif

默认的情况下它并没有指向MyVue。

钩子函数的执行顺序

我们在Vue原型的_init方法中,首先看到的是callHook(vm, 'beforeCreate'),然后接下来是

 initInjections(vm) // resolve injections before data/props initState(vm) initProvide(vm) // resolve provide after data/props
b71ff3c448069ea76e0e8f3066773a5b.png

随后调用初始化注入,状态,创建data,props,完成以后再来调用created钩子函数。所以我们在created中可以访问到data中的数据,而在beforeCreate中不能访问。

我们来验证一下。

faf822a6e2f768f5d9b8e837f6f9af65.gif

可以清楚的看到在beforeCreate中不能访问data中的数据。而在created中可以。

再接着往下看走,我们进到lifecycle.js中去。我找到了一个叫mountComponent的函数。

dcabfc29451f1e6e77576ec9ce8a0cf3.png

了解Vue的都知道,这个钩子函数是在挂载dom节点之前,再往下走。我找到了mounted钩子,

324d0b12f3b6be739707e30d30571679.png

那么在beforeMount和mounted之间,vue其实是做的dom节点的渲染,我们来找下这中间的源码。

2f7563d3b6c544b1408e38cf9db81ebf.png

beforeMount和mounted之间会有一个_render()方法的调用,那么这个方法本身就是渲染的意思,将我们的虚拟dom渲染绑定到真实的dom节点上。(_render方法的源码我没找着,知道的麻烦告知一下,^_^)

结论:我们在beforeMount中不能使用this.$refs[name]去访问真实的dom节点,而在mounted钩子中可以,我们也来验证一下。

d18d224cbe5c607c7b271808191fdc3b.gif

可以看到在mounted中可以访问到msg,而在beforeMounted中则不行。

后面的钩子大家我就不再一一列举了。

总结:

  1. 如何去阅读当下热门的JS框架,阅读源码该如何下手
  2. 从源码分析Vue生命周期中的各个钩子函数的源码,彻底搞明白官网中介绍的每一个钩子函数的执行原理。
  3. 结合源码和vue教程综合学习Vue框架,效果会更好。

这里是畅哥聊技术 《从源码中学Vue》系列文章,更多精彩内容持续更新中,敬请期待。

未完待续。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值