Vue.js 源码分析(九) 基础篇 生命周期详解
先来看看官网的介绍:
主要有八个生命周期,分别是:
beforeCreate、created、beforeMount、mounted、beforeupdate、updated 、beforeDestroy和destroyed,分别对应八个不同的时期,另外还有两个activated和deactivated生命周期是对应Keep-Alive组件的
关于这八个生命周期的具体用法官网介绍的很详细了,飞机入口:点我点我 ,另外还有一张比较直观图形介绍,飞机入口:点我点我
例如:
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script><title>Document</title> </head> <body><div id="app"><p>{{message}}</p><button @click="test1()">测试(更新操作)</button><button @click="test2()">测试(销毁操作)</button></div><script>Vue.config.productionTip=false;Vue.config.devtools=false;new Vue({el:'#app',data:{message:"Hello World!"},beforeCreate:function(){ console.log('beforeCreate'); },created:function(){ console.log('created'); },beforeMount:function(){ console.log('beforeMount'); }, mounted:function(){ console.log('mounted'); },beforeUpdate:function(){ console.log('beforeUpdate'); },updated:function(){ console.log('updated'); },beforeDestroy:function(){ console.log('beforeDestroy'); },destroyed:function(){ console.log('destroyed'); },methods:{test1:function(){this.message="Hello Vue!";},test2:function(){this.$destroy();},}})</script> </body> </html>
页面渲染如下:
渲染完成后控制台输出:
当点击了测试(更新操作)这个按钮后,修改了Vue实例的message值做了更新操作,此时控制台输出如下:
当我们点击测试(销毁操作)按钮时,Vue实例做了销毁操作,控制台输出如下:
对于Vue的插件(包括官方的生态)来说,绝大多数都用到了beforeCreate()这个生命周期函数,可以在实例化前混入一些属性,以vuex为例,如下:
function applyMixin (Vue) {var version = Number(Vue.version.split('.')[0]);if (version >= 2) { Vue.mixin({ beforeCreate: vuexInit }); //如果Vue的版本大于2,则将vuexInit混入到beforeCreate生命周期函数,这样vuex就会进行初始化 } else { // override init and inject vuex init procedure // for 1.x backwards compatibility. var _init = Vue.prototype._init; Vue.prototype._init = function (options) { if ( options === void 0 ) options = {}; options.init = options.init ? [vuexInit].concat(options.init) : vuexInit; _init.call(this, options); }; }
vue-router也是的,如下:
Vue.mixin({ //混入了两个生命周期,分别是beforeCreate和destroyedbeforeCreate: function beforeCreate () {if (isDef(this.$options.router)) { this._routerRoot = this; this._router = this.$options.router; this._router.init(this); Vue.util.defineReactive(this, '_route', this._router.history.current); } else { this._routerRoot = (this.$parent && this.$parent._routerRoot) || this; } registerInstance(this, this); }, destroyed: function destroyed () { registerInstance(this); } });
源码分析
生命周期的源码实现比较简单,都是通过Vue内部的一个叫callHook()的全局函数执行的,如下:
function callHook (vm, hook) { //第2914行 vm:vue实例 hook:对应的操作名(例如:beforeCreate、created等)// #7573 disable dep collection when invoking lifecycle hooks pushTarget();var handlers = vm.$options[hook]; //获取生命周期函数 if (handlers) {for (var i = 0, j = handlers.length; i < j; i++) { //遍历生命周期函数try {handlers[i].call(vm); //执行该函数,以vm作为上下文} catch (e) {handleError(e, vm, (hook + " hook"));}}}if (vm._hasHookEvent) {vm.$emit('hook:' + hook);}popTarget(); }
beforeCreate和created是在init()的时候执行的,如下:
Vue.prototype._init = function (options) { //第4576行/*略*/vm._self = vm;initLifecycle(vm);initEvents(vm);initRender(vm);callHook(vm, 'beforeCreate'); //执行beforeCreate生命周期函数initInjections(vm); // resolve injections before data/props initState(vm);initProvide(vm); // resolve provide after data/propscallHook(vm, 'created'); //执行created生命周期函数/*略*/};
beforeMount和mounted是在挂载的时候在mountComponent()里执行的,如下:
function mountComponent(vm, el, hydrating) { //第2739行 挂载组件 vm:Vue实例 el:真实的DOM节点对象 /*略*/callHook(vm, 'beforeMount'); //挂载前 执行生命周期里的beforeMount事件var updateComponent;if ("development" !== 'production' && config.performance && mark) { //开启了性能追踪时的分支/*略*/} else {updateComponent = function () {vm._update(vm._render(), hydrating);}; }new Watcher(vm, updateComponent, noop, null, true); hydrating = false;if (vm.$vnode == null) { vm._isMounted = true; //设置vm._isMounted为true,表示已挂载callHook(vm, 'mounted'); //执行生命周期里的Mount事件 }return vm }
beforeUpdate是在Vue原型上的_update更新时触发的,如下:
Vue.prototype._update = function (vnode, hydrating) { //第2646行var vm = this;if (vm._isMounted) { //如果已经挂载了,则表示已经挂载了callHook(vm, 'beforeUpdate'); //则触发beforeUpdate }/*略*/ }
updated是在nextTick()执行时当watcher执行完了之后触发的,如下:
function callUpdatedHooks (queue) { //第3016行var i = queue.length;while (i--) {var watcher = queue[i];var vm = watcher.vm;if (vm._watcher === watcher && vm._isMounted) { //如果当前是渲染watcher,且已经挂载了callHook(vm, 'updated'); //则触发update生命周期函数 }} }
beforeDestroy和destroyed是在Vue原型的$destroy()方法里触发的,如下:
Vue.prototype.$destroy = function () { //第2695行var vm = this;if (vm._isBeingDestroyed) {return}callHook(vm, 'beforeDestroy'); //触发beforeDestroy生命周期函数/*这里进行销毁过程*/callHook(vm, 'destroyed'); //触发destroyed生命周期函数/*略*/}; }
转载于:https://www.cnblogs.com/greatdesert/p/11062881.html
Vue.js 源码分析(九) 基础篇 生命周期详解相关推荐
- Vue.js 源码分析(五) 基础篇 方法 methods属性详解
methods中定义了Vue实例的方法,官网是这样介绍的: 例如:: <!DOCTYPE html> <html lang="en"> <head&g ...
- linux权限源码分析,Linux基础之文件权限详解
Linux中对于权限的制定虽然没有Windows的那么精细,但是如果你了解并掌握Linux中文件的权限知识,也可以像Windows那样对权限做到精确配置. Linux中的文件权限是什么? 如何查看Li ...
- Vue.js 源码分析(二十三) 指令篇 v-show指令详解
v-show的作用是将表达式值转换为布尔值,根据该布尔值的真假来显示/隐藏切换元素,它是通过切换元素的display这个css属性值来实现的,例如: <!DOCTYPE html> < ...
- Spring源码分析系列-Bean的生命周期(总结篇)
ApplicationContext和BeanFactory BeanFactory是Spring中的顶层接口,只负责管理bean,而ApplicationContext也实现了BeanFacto ...
- Kafka源码分析10:副本状态机ReplicaStateMachine详解 (图解+秒懂+史上最全)
文章很长,建议收藏起来,慢慢读! Java 高并发 发烧友社群:疯狂创客圈 奉上以下珍贵的学习资源: 免费赠送 经典图书:<Java高并发核心编程(卷1)> 面试必备 + 大厂必备 +涨薪 ...
- Spring源码分析之Bean的创建过程详解
前文传送门: Spring源码分析之预启动流程 Spring源码分析之BeanFactory体系结构 Spring源码分析之BeanFactoryPostProcessor调用过程详解 本文内容: 在 ...
- Vue.js 源码分析—— Slots 是如何实现的
今天主要分析 Vue.js 中常用的 Slots 功能是如何设计和实现的.本文将分为普通插槽.作用域插槽以及 Vue.js 2.6.x 版本的 v-slot 语法三部分进行讨论. 本文属于进阶内容,如 ...
- 从源码分析RocketMQ系列-RocketMQ消息设计详解
1 消息存储 消息存储是RocketMQ中最为复杂和最为重要的一部分,本节将分别从RocketMQ的消息存储整体架构.PageCache与Mmap内存映射以及RocketMQ中两种不同的刷盘方式三 ...
- Glide源码分析3 -- 绑定Activity生命周期
1. 概述和核心类 Glide中一个重要特性是Request可以随Activity或Fragment的onStart而resume,onStop而pause,onDestroy而clear,从而节约流 ...
最新文章
- PHP mysql数据迁移,【MySQL】迁移数据目录php-php教程
- 光纤看起来长得都一样?其实它们之间大有不同—Vecloud微云
- 汽车abs matlab仿真模糊pid控制
- spring boot 开源项目汇总
- php中英文手册(集成用户注释08/12/2007)
- mysql5.7 innodb myisam 区别_InnoDB与MyISAM的区别(高性能MySQL笔记)
- python的turtle画小人_Pythonturtle画图库画姓名实例
- “才子进销存”新一代真正基于互联网(Internet)的进销存分销管理软件
- 有效解决vue动态绑定多个class的官方实例语法无效的问题
- 怎么解决IPA processing failed错误, 用xcode 11打包
- vba中find用法
- Java 原生 PCM 格式文件转 WAV
- 茆诗松概率论与数理统计持续更新中...
- HTML实现猜数字游戏
- 移动端框架之mand-mobile
- 推荐系统实践(八)UCG 利用ltf-idf方法
- NOIP2022.11.23模拟赛
- 丢失LDF文件怎么办?
- 再批国标数学教材的微分定义
- EXCELVBA: 中国热力图 HeatMap of China