Vue学习系列(四)——理解生命周期和钩子
前言
在上一篇中,我们对平时进行vue开发中遇到的常用指令进行归类说明讲解,大概已经学会了怎么去实现数据绑定,以及实现动态的实现数据展示功能,运用指令,可以更好更快的进行开发。而在这一篇中,我们将通过实例,探究vue的生命周期。
万物皆有灵,世间万物都拥有灵魂,小到山河湖海,花草树木,蚂蚁到人类,以及所有的动植物,大到地球星空和宇宙,都拥有灵魂,可以说他们都是有生命的,只是他们的生命形态是我们人类所不能理解的存在。在生产中,生命周期通俗来讲,就是从自然中来回到自然中去的全过程,也就是从采集材料设计,到加工生产后流通使用的过程,以及产品报废,进而回归大自然的过程,这整个过程就是一个完整的生命周期。因此,在开发应用项目的中,从启动页面的加载,页面渲染到销毁,也算是生命周期。Vue把整个生命周期划分为创建、挂载、更新、销毁等阶段,每个阶段都会给一些“钩子”让我们来做一些我们想实现的动作。这里的“钩子”可以这么理解,就是在每一个阶段用钩子钩住,并进行响应的操作。

学习生命周期,可以使我们更好的理解Vue的生命机制,通过了解每个阶段的钩子,可以更好的实现我们的业务代码,处理更加复杂的业务逻辑。
内容
Vue每一个组件都有属于自己的生命周期,从开始创建、初始化数据、编译模板、挂载Dom、渲染→更新→渲染、卸载等这就是一个组件的生命周期。
在整个生命周期内,总共分为8个阶段创建前/后,载入前/后,更新前/后,销毁前/后。

执行顺序

*图片来自官网,只要你理解了这张图,也就对Vue的生命周期有了一个大致的了解。
在谈到Vue的生命周期的时候,我们首先需要创建一个实例:
开始
一、创建前/后:
1.beforeCreate-创建前 :实例创建前:这个阶段实例的data、methods是读不到的(el 和 data 并未初始化)
var app = new Vue({
el: '#app',
data: {
message : "这是艾三元的主页"
},
beforeCreate: function () {
console.group('beforeCreate 组件刚刚被创建,组件属性计算前状态===============》');
console.log("%c%s", "color:red" , "el : " + this.$el); //undefined
console.log("%c%s", "color:red","data : " + this.$data); //undefined
console.log("%c%s", "color:red","message: " + this.message) //undefined
},
})

2.created-创建完成 :实例创建后:这个阶段已经完成了数据观测(data observer),属性和方法的运算, watch/event 事件回调。mount挂载阶段还没开始,$el 属性目前不可见,数据并没有在DOM元素上进行渲染(完成了data数据的初始化,el没有)
var app = new Vue({
el: '#app',
data: {
message : "这是艾三元的主页"
},
created: function () {
console.group('created 组件创建完毕,属性已经绑定但dom还未生成的状态===============》');
console.log("%c%s", "color:red","el : " + this.$el); //undefined
console.log("%c%s", "color:red","data : " + this.$data); //已被初始化
console.log("%c%s", "color:red","message: " + this.message); //已被初始化
},
})

二、载入前/后
1.beforeMount :准备载入——在挂载开始之前被调用:相关的 render 函数首次被调用。程序运行,控制台看输出 (完成了虚拟el和data初始化)
var app = new Vue({
el: '#app',
data: {
message : "这是艾三元的主页"
},
beforeMount: function () {
console.group('beforeMount 模板挂载前状态===============》');
console.log("%c%s", "color:red","el : " + (this.$el)); //已被初始化
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data); //已被初始化
console.log("%c%s", "color:red","message: " + this.message); //已被初始化
},
})

2.mounted :挂载完成——el选项的DOM节点 被新创建的 vm.$el 替换,并挂载到实例上去之后调用此生命周期函数。此时实例的数据在DOM节点上进行渲染(完成了真实el和data初始化)
var app = new Vue({
el: '#app',
data: {
message : "这是艾三元的主页"
},
mounted: function () {
console.group('mounted 模板挂载结束状态===============》');
console.log("%c%s", "color:red","el : " + this.$el); //已被初始化
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data); //已被初始化
console.log("%c%s", "color:red","message: " + this.message); //已被初始化
},
})

这个时候,页面渲染的四个阶段已经完成了,我们看看流程:(刚开始的时候beforeCreate阶段,数据和页面都没有渲染,但是页面的静态数据已经被加载出来,然后一步一步,先vue实例,然后挂载,到最后页面渲染完成)
三、更新前/后
1.beforeUpdate :更新Data之前——数据更新时调用,但不进行DOM重新渲染,在数据更新时DOM没渲染前可以在这个生命函数里进行状态处理
当修改vue实例的data时,vue就会自动帮我们更新渲染视图,在这个过程中,vue提供了beforeUpdate的钩子给我们,在检测到我们要修改数据的时候,更新渲染视图之前就会触发钩子beforeUpdate。
var app = new Vue({
el: '#app',
data: {
message : "这是艾三元的主页"
},
beforeUpdate: function () {
console.group('beforeUpdate 更新前状态===============》');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data);
console.log("%c%s", "color:red","message: " + this.message);
},
})
控制台输入 app.message = '艾三元'

由图看来,我们的 Data 数据已经更新了,但是页面里还没有更新
2.update :这个状态下数据更新并且DOM重新渲染,当这个生命周期函数被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。当实例每次进行数据更新时updated都会执行
var app = new Vue({
el: '#app',
data: {
message : "这是艾三元的主页"
},
updated: function () {
console.group('updated 更新完成状态===============》');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data);
console.log("%c%s", "color:red","message: " + this.message);
},
})

四、销毁前/后
1.beforeDestroy :页面销毁前——实例销毁之前调用。调用实例的destroy( )方法可以销毁当前的组件,在销毁前,会触发beforeDestroy钩子。
var app = new Vue({
el: '#app',
data: {
message : "这是艾三元的主页"
},
beforeDestroy: function () {
console.group('beforeDestroy 销毁前状态===============》');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data);
console.log("%c%s", "color:red","message: " + this.message);
},
})
控制台输入 app.$destroy()

2.destroyed :销毁完成——Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
var app = new Vue({
el: '#app',
data: {
message : "这是艾三元的主页"
},
destroyed: function () {
console.group('destroyed 销毁完成状态===============》');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data);
console.log("%c%s", "color:red","message: " + this.message)
}
})

这个时候我们可以看到,vue 实例被销毁后,再修改 Data 页面也已经不能修改页面 DOM 了。
源码
<!DOCTYPE html>
<html>
<head>
<title></title>
<script type="text/javascript" src="https://cdn.jsdelivr.net/vue/2.1.3/vue.js"></script>
</head>
<body> <div id="app">
<p>{{ message }}</p>
</div> <script type="text/javascript"> var app = new Vue({
el: '#app',
data: {
message : "这是艾三元的主页"
},
beforeCreate: function () {
console.group('beforeCreate 组件刚刚被创建,组件属性计算前状态===============》');
console.log("%c%s", "color:red" , "el : " + this.$el); //undefined
console.log("%c%s", "color:red","data : " + this.$data); //undefined
console.log("%c%s", "color:red","message: " + this.message) //undefined
},
created: function () {
console.group('created 组件创建完毕,属性已经绑定但dom还未生成的状态===============》');
console.log("%c%s", "color:red","el : " + this.$el); //undefined
console.log("%c%s", "color:red","data : " + this.$data); //已被初始化
console.log("%c%s", "color:red","message: " + this.message); //已被初始化
},
beforeMount: function () {
console.group('beforeMount 模板挂载前状态===============》');
console.log("%c%s", "color:red","el : " + (this.$el)); //已被初始化
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data); //已被初始化
console.log("%c%s", "color:red","message: " + this.message); //已被初始化
},
mounted: function () {
console.group('mounted 模板挂载结束状态===============》');
console.log("%c%s", "color:red","el : " + this.$el); //已被初始化
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data); //已被初始化
console.log("%c%s", "color:red","message: " + this.message); //已被初始化
},
beforeUpdate: function () {
console.group('beforeUpdate 更新前状态===============》');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data);
console.log("%c%s", "color:red","message: " + this.message);
},
updated: function () {
console.group('updated 更新完成状态===============》');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data);
console.log("%c%s", "color:red","message: " + this.message);
},
beforeDestroy: function () {
console.group('beforeDestroy 销毁前状态===============》');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data);
console.log("%c%s", "color:red","message: " + this.message);
},
destroyed: function () {
console.group('destroyed 销毁完成状态===============》');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data);
console.log("%c%s", "color:red","message: " + this.message)
}
})
</script>
</body>
</html>
附加说明
1.说说钩子是什么时候触发的?
Vue文档源码:在实例化的时候
function Vue(opt){
this._init(opt)
}
Vue.prototype._init(opt){
... 合并选项
... 设置初始值 ,事件 等数据
initLifecycle(vm)
callHook(vm, 'beforeCreate');
... 初始化选项等数据
callHook(vm, 'created');
...获取挂载的DOM 父节点
callHook(vm, 'beforeMount');
...解析模板成渲染函数,并执行渲染函数,生成DOM插入页面
vm._isMounted = true;
callHook(vm, 'mounted');
}
// 组件更新时会调用这个函数
Vue.prototype._update = function(
vnode, hydrating
) {
if (vm._isMounted) {
callHook(vm, 'beforeUpdate');
}
...重新调用渲染函数,对比旧节点和新节点,得到最小差异,然后只更新这部分页面
callHook(vm, 'updated');
}
// 节点被移除时会调用这个函数
Vue.prototype.$destroy = function() {
callHook(vm, 'beforeDestroy');
vm._isBeingDestroyed = true;
...实例被消除,移除所有 watcher
vm._isDestroyed = true;
...DOM被移除
callHook(vm, 'destroyed');
}
在执行钩子的时候,会触发这个函数,遍历执行,绑定上下文
function callHook(vm, hook) {
// 是自己传入的 created 等回调
var handlers = vm.$options[hook];
if (handlers) {
for (var i = ,j = handlers.length; i < j; i++) {
handlers[i].call(vm);
}
}
}
总结
1.通过简单了解 Vue 生命周期的八个阶段,可以应用在之后的开发中,针对不同的阶段的钩子采取不同的操作,更好的实现我们的业务代码,处理更加复杂的业务逻辑。
2.参考资料Vue官网
3.下一篇开始创建项目应用
Vue学习系列(四)——理解生命周期和钩子的更多相关文章
- vue学习(五)生命周期 的钩子函数
生命周期的钩子函数 主要有以下几种 beforeCreate created beforeMount mounted beforeUpdate updated activated deactivate ...
- [前端] VUE基础 (5) (过滤器、生命周期、钩子函数)
一.过滤器 过滤器分为局部过滤器和全局过滤器. 1.局部过滤器 <body> <div id="app"> </div> <script ...
- Maven学习(四)-- 生命周期和插件
标签(空格分隔): 学习笔记 Maven生命周期是抽象的,不做任何实际的工作,在Maven的设计中,实际的任务都交由插件来完成. 每个构件步骤都可以绑定一个或者多个插件行为,而且Maven为大多数构建 ...
- Vue – 基础学习(1):对生命周期和钩子函的理解
一.简介 先贴一下官网对生命周期/钩子函数的说明(先贴为敬):所有的生命周期钩子自动绑定 this 上下文到实例中,因此你可以访问数据,对属性和方法进行运算.这意味着你不能使用箭头函数来定义一个生命周 ...
- vue学习之生命周期和钩子函数
参考文章:Vue2.0 探索之路——生命周期和钩子函数的一些理解 抛出问题: 我们有时候会在几个钩子函数里做一些事情,那么什么时候做,该在哪个函数里做? 生命周期简介 结合代码看el 和 data以及 ...
- vue学习笔记(二)vue的生命周期和钩子函数
前言 通过上一章的学习,我们已经初步的了解了vue到底是什么东西,可以干什么,而这一篇博客主要介绍vue的生命周期和它常用的钩子函数,如果有学过java的园友可能有接触到在学习servlet的时候学过 ...
- Android学习整理之Activity生命周期篇
一.Activity生命周期说明 Activity的四种状态: ⒈活动状态(Active or Running):也称为运行状态,处于Activity栈顶,在用户界面中最上层,完全能被用户看到,能 ...
- 【转】Android总结篇系列:Activity生命周期
[转]Android总结篇系列:Activity生命周期 Android官方文档和其他不少资料都对Activity生命周期进行了详细介绍,在结合资料和项目开发过程中遇到的问题,本文将对Activity ...
- Vue(3)- 安装脚手架、过滤器、生命周期的钩子函数、vue-router基本使用
一.安装脚手架 1.下载node.js,本文下载版本为node-v8.12.0-x64.msi,一键式安装. 2.安装完成后,打开终端,输入node,可进入node环境(两次ctrl+c退出),如下图 ...
随机推荐
- 详解http报文
摘要 作为一个web开发者,每天都在使用者Http协议,却总是一知半解.本文参看Http RFC7230规范,梳理了http报文部分. http 报文构成 start-line: 起始行,描述请求或响 ...
- springboot系列之02-需要了解的宏观知识点
未经允许,不得转载 原作者:字母哥博客 本文完整系列出自:springboot深入浅出系列 一.Spring Boot . Spring MVC .Spring对比 首先你需要明白一件事情:Sprin ...
- 跟文档学习next.js
前言:Next.js 是一个轻量级的 React 服务端渲染应用框架. Next.js中文点击这里 Next.js中文站Github点击这里 新建文件夹安装它: npm install --save ...
- Stanford公开课《编译原理》学习笔记(2)递归下降法
目录 一. Parse阶段 CFG Recursive Descent(递归下降遍历) 二. 递归下降遍历 2.1 预备知识 2.2 多行语句的处理思路 2.3 简易的文法定义 2.4 文法产生式的代 ...
- Linux之修改系统密码
目录 Linux之修改系统密码 参考 RHEL6修改系统密码 RHEL7修改系统密码 Linux之修改系统密码
- js常用Matn函数的操练
Math.PI console.log(Math.PI); 随机数以及向下取整 这是一个能实现从a-b之间随机打印一个整数 function rand_s(a, b) { var x = a + (b ...
- Zookeeper 学习笔记之 Leader Election
ZooKeeper四种节点类型: Persist Persist_Sequential Ephemeral Ephemeral_Sequential 在节点上可注册的Watch,客户端先得到通知再得到 ...
- Kafka 学习笔记之 架构
Kafka的概念: 1. AMQP协议 Advanced Message Queuing Protocol (高级消息队列协议) The Advanced Message Queuing Protoc ...
- Flume 学习笔记之 Flume NG+Kafka整合
Flume NG集群+Kafka集群整合: 修改Flume配置文件(flume-kafka-server.conf),让Sink连上Kafka hadoop1: #set Agent name a1. ...
- PHP的bcmath编译安装
问题描述:zabbix编译安装时PHP条件检查失败,如下图: 解决办法: 1.PHP自带bcmath扩展模块,可直接进行编译安装. [root@localhost etc]# cd /usr/loca ...