先来看看官网的介绍:

主要有八个生命周期,分别是:

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实例做了销毁操作,控制台输出如下:

writer by:大沙漠 QQ:22969969

对于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和destroyed
beforeCreate: 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/props
callHook(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生命周期函数
/*略*/
};
}

Vue.js 源码分析(九) 基础篇 生命周期详解的更多相关文章

  1. Vue.js 源码分析(十) 基础篇 ref属性详解

    ref 被用来给元素或子组件注册引用信息.引用信息将会注册在父组件的 $refs 对象上.如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素:如果用在子组件上,引用就指向组件实例,例如: ...

  2. Vue.js 源码分析(十三) 基础篇 组件 props属性详解

    父组件通过props属性向子组件传递数据,定义组件的时候可以定义一个props属性,值可以是一个字符串数组或一个对象. 例如: <!DOCTYPE html> <html lang= ...

  3. Vue.js 源码分析(四) 基础篇 响应式原理 data属性

    官网对data属性的介绍如下: 意思就是:data保存着Vue实例里用到的数据,Vue会修改data里的每个属性的访问控制器属性,当访问每个属性时会访问对应的get方法,修改属性时会执行对应的set方 ...

  4. Vue.js 源码分析(三) 基础篇 模板渲染 el、emplate、render属性详解

    Vue有三个属性和模板有关,官网上是这样解释的: el ;提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标 template ;一个字符串模板作为 Vue 实例的标识使用.模板将会 ...

  5. Vue.js 源码分析(二) 基础篇 全局配置

    Vue.config是一个对象,包含Vue的全局配置,可以在启动应用之前修改下列属性,如下: ptionMergeStrategies        ;自定义合并策略的选项silent         ...

  6. Vue.js 源码分析(八) 基础篇 依赖注入 provide/inject组合详解

    先来看看官网的介绍: 简单的说,当组件的引入层次过多,我们的子孙组件想要获取祖先组件的资源,那么怎么办呢,总不能一直取父级往上吧,而且这样代码结构容易混乱.这个就是这对选项要干的事情 provide和 ...

  7. Vue.js 源码分析(七) 基础篇 侦听器 watch属性详解

    先来看看官网的介绍: 官网介绍的很好理解了,也就是监听一个数据的变化,当该数据变化时执行我们的watch方法,watch选项是一个对象,键为需要观察的数据名,值为一个表达式(函数),还可以是一个对象, ...

  8. Vue.js 源码分析(十一) 基础篇 过滤器 filters属性详解

    Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化.过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持).过滤器应该被添加在 JavaScrip ...

  9. Vue.js 源码分析(五) 基础篇 方法 methods属性详解

    methods中定义了Vue实例的方法,官网是这样介绍的: 例如:: <!DOCTYPE html> <html lang="en"> <head&g ...

随机推荐

  1. 【转载】每个 Android 开发者必须知道的消息机制问题总结

    Android的消息机制几乎是面试必问的话题,当然也并不是因为面试,而去学习,更重要的是它在Android的开发中是必不可少的,占着举足轻重的地位,所以弄懂它是很有必要的.下面就来说说最基本的东西. ...

  2. tcp粘包、解决粘包问题

    目录 subproess模块 TCP粘包问题 粘包两种情况 解决粘包问题 struct模块的使用 使用struct模块解决粘包 优化解决粘包问题 上传大文件 服务端 客户端 UDP协议 upd套接字 ...

  3. rabbitmq pika(python)订阅发布多客户端消费场景简单使用

    发布端: import pika import time credentials = pika.credentials.PlainCredentials('root', 'root',erase_on ...

  4. JSON理解(一篇就够了)

    可以看看视频讲解,视频几十分钟就结束了 JSON 1.什么是json 其实是一种数据格式的规范,与开发的语言无关,轻量级的数据格式 全称JavaScript Object Notation 2.优点: ...

  5. Mybatis-plus中的常用注解

    @TableName:数据库表相关 @TableId:表主键标识 @TableField:表字段标识 @TableLogic:表字段逻辑处理注解(逻辑删除) @TableId(type= IdType ...

  6. DRF视图功能介绍(2)

    本帖最后由 杰哥,我就服你 于 2018-12-20 13:22 编辑 Django rest framework(DRF) D:是一个用于构建Web API强大又灵活的框架,基于Django框架二次 ...

  7. 接口测试中GET和POST两种基本HTTP请求方法的区别

    面试时,可以回答(一般答前4条就行): GET参数通过url传递,POST放在request body中 GET请求在url中传递的参数是有长度限制的,而POST没有 GET比POST更不安全,因为参 ...

  8. luoguP5283 [十二省联考2019]异或粽子

    题意 类似超级钢琴,找最优解用可持久化trie. code: #include<bits/stdc++.h> using namespace std; #define re registe ...

  9. <Tree> 298 250 366 199(高频) 98(高频)

    298. Binary Tree Longest Consecutive Sequence 先序遍历,根左右.如果该节点的 value == 父节点value + 1, 则长度+1; 否则重置为1. ...

  10. h5移动端页面强制横屏

    说明:这个的原文章来自于https://www.jianshu.com/p/9c3264f4a405  ,我做点点补充  ,谢谢原链接的小姐姐 最近公司是要我做一个h5的小视频,因为是视频接视频,并且 ...