先来看看官网的介绍:

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

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. 如何开发优质的 Flutter App:Flutter App 软件测试指南

    继上一场GitChat文章发布之后,博主又为朋友们带来另一场Chat.这一次我们主要聊一聊Flutter App的测试环节. 众所周知,应用的功能越多,手动测试的难度就越大.一套完整的自动化测试将帮助 ...

  2. jQuery Migrate 插件用法

    jQuery Migrate是应用迁移辅助插件,是用于高级版本兼容低级版本辅助插件.例如jQuery版本用的是1.x,计划升级到3.x,就可以在页面删除1.x版本,换成3.x版本,如果有脚本错误,就引 ...

  3. 软工个人项目(Java实现)

    一. Github地址: https://github.com/RuiBingo/PersonalWork 二.个人PSP表格: PSP2.1 PSP阶段 预估耗时(分钟) 实际耗时(分钟) Plan ...

  4. [b0042] python 归纳 (二七)_gui_tkinter_基本使用

    # -*- coding: utf-8 -*- """ 学习 Tkinter画图基本控件使用 逻辑: 放几个 输入控件.点击按钮,将输入控件内容打印出来 使用: 1. 创 ...

  5. [20191010]bash行计算器.txt

    [20191010]bash行计算器.txt --//写一个bash行计算器,为了避免冲突,函数命名为2个=,1个=感觉不是很好(心里上^_^).--//使用bc计算器,里面函数不能使用圆括号,使用中 ...

  6. BayaiM__Linux安装MySQL的两种方法

    BayaiM__Linux安装MySQL的两种方法     < 以下内容,纯属抄袭,如有雷同,爱咋咋地 >  阅读(21210) | 评论(4340) | 转发(5660) | 删除 编辑 ...

  7. c++ 多态的内幕

    c++ 多态,就是利用了一个二级指针(指针数组),数组里的每个元素都指向了,用virtual修饰的成员函数. 既然提到了指针,那就让我们用内存地址来证明一下吧. 为了证明,我们必须要取到成员函数的首地 ...

  8. dockerfile和资源限制(五)

    镜像生成途径 dockerfile 基于容器制作 什么是dockerfile dockerfile说白就是用来构建docker 镜像的源码,大家看到源码俩字不用惊慌,所为的dockerfile源码只是 ...

  9. STM32HAL快速上手

    STM32HAL快速上手 资料下载 如果在下面的网站中没有账户,建议用edu邮箱创建账户. STMicroeletronic 意法半导体官网 首页 - STMicroelectronics 意法半导体 ...

  10. Windows | Ubuntu18.04分别安装Matlab 2017b破解版

    首先下载好Windows和Ubuntu 版本的MATLAB 2017b 安装包, 1.Windows上安装,解压文件R2017b_win64_dvd1.iso和R2017b_win64_dvd2.is ...