当前位置: 首页 > news >正文

初探 Vue 生命周期和钩子函数

生命周期

生命周期函数就是 Vue 实例在某一个时间点会自动执行的函数。

简单来说就是好像把人的出生到死亡分成一个个阶段,你取名字肯定是在你出生阶段,而不是在成年阶段;你结婚肯定是在成年阶段,而不是在出生阶段;如果说你在出生阶段想去阶段,那肯定是不行的。
组件也是一样,在实例化的时特定阶段调用特定方法,调用的这个方法就是钩子函数。

钩子函数

钩子函数和回调函数有什么区别吗?

它们区别是:

js派函数监听事件 => 监听函数就是所谓的钩子函数 => 函数钩取事件:函数主动找事件 => 钩子函数

js预留函数给dom事件,dom事件调用js预留的函数 => 事件派发给函数:事件调用函数 => 回调函数

打个比方:

钩子函数:一个房间里的监控摄像头监控着每一个进入的人的面部特征,识别出了符合条件的人就触发警告(执行函数事件);

回调函数:可以看做是在一片地区埋了许许多多的地雷,一旦踩中了某个地雷(触发事件),地雷就会爆炸(执行函数事件)。

可以简单的理解为:

钩子函数是事件被动的监听,一旦条件触发就执行

回调函数是主动事件,执行函数体内容

生命周期探究

<template>
    <div>{{msg}}</div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'hello world',
      msg1: ''
    }
  },
  beforeCreate () {
    console.groupCollapsed('beforeCreate 创建前状态')
    console.log('%c%s', 'color:MediumVioletRed', 'el     : ' + this.$el)
    console.log(this.$el)
    console.log('%c%s', 'color:MediumVioletRed', 'data   : ' + this.$data)
    console.log(this.$data)
    console.log('%c%s', 'color:MediumVioletRed', 'msg: ' + this.msg)
    console.groupEnd()
  },
  created () {
    console.groupCollapsed('created 创建前状态')
    console.log('%c%s', 'color:MediumVioletRed', 'el     : ' + this.$el)
    console.log(this.$el)
    console.log('%c%s', 'color:MediumVioletRed', 'data   : ' + this.$data)
    console.log(this.$data.msg)
    console.log('%c%s', 'color:MediumVioletRed', 'msg: ' + this.msg)
    console.groupEnd()
  },
  beforeMount () {
    console.groupCollapsed('beforeMount 挂载前状态')
    console.log('%c%s', 'color:MediumVioletRed', 'el     : ' + this.$el)
    console.log(this.$el)
    console.log('%c%s', 'color:MediumVioletRed', 'data   : ' + this.$data)
    console.log(this.$data.msg)
    console.log('%c%s', 'color:MediumVioletRed', 'msg: ' + this.msg)
    console.groupEnd()
  },
  mounted () {
    console.groupCollapsed('mounted 挂载后状态')
    console.log('%c%s', 'color:MediumVioletRed', 'el     : ' + this.$el)
    console.log(this.$el)
    console.log('%c%s', 'color:MediumVioletRed', 'data   : ' + this.$data)
    console.log(this.$data.msg)
    console.log('%c%s', 'color:MediumVioletRed', 'msg: ' + this.msg)
    console.groupEnd()
    setTimeout(() => {
      this.$data.msg = '123'
    }, 5000)
  },
  activated () {
    console.groupCollapsed('activated 挂载后状态')
    console.log('%c%s', 'color:MediumVioletRed', 'el     : ' + this.$el)
    console.log(this.$el)
    console.log('%c%s', 'color:MediumVioletRed', 'data   : ' + this.$data)
    console.log(this.$data.msg)
    console.log('%c%s', 'color:MediumVioletRed', 'msg: ' + this.msg)
    console.groupEnd()
    setTimeout(() => {
      this.$data.msg = 'hello tiantian'
    }, 10000)
  },
  beforeUpdate () {
    console.groupCollapsed('beforeUpdate 更新前状态')
    console.log('%c%s', 'color:MediumVioletRed', 'el     : ' + this.$el)
    console.log(this.$el)
    console.log('%c%s', 'color:MediumVioletRed', 'data   : ' + this.$data)
    console.log(document.getElementById('app').innerHTML)
    console.log('%c%s', 'color:MediumVioletRed', 'msg: ' + this.msg)
    console.groupEnd()
  },
  updated () {
    console.groupCollapsed('updated 更新后状态')
    console.log('%c%s', 'color:MediumVioletRed', 'el     : ' + this.$el)
    console.log(this.$el)
    console.log('%c%s', 'color:MediumVioletRed', 'data   : ' + this.$data)
    console.log(document.getElementById('app').innerHTML)
    console.log('%c%s', 'color:MediumVioletRed', 'msg: ' + this.msg)
    console.groupEnd()
    setTimeout(() => {
      this.$destroy()
    }, 5000)
  },
  beforeDestroy () {
    console.groupCollapsed('beforeDestroy 实例销毁前状态')
    console.log('%c%s', 'color:MediumVioletRed', 'el     : ' + this.$el)
    console.log(this.$el)
    console.log('%c%s', 'color:MediumVioletRed', 'data   : ' + this.$data)
    console.log(document.getElementById('app').innerHTML)
    console.log('%c%s', 'color:MediumVioletRed', 'msg: ' + this.msg)
    console.groupEnd()
  },
  destroyed () {
    console.groupCollapsed('destroyed 实例销毁后状态')
    console.log('%c%s', 'color:MediumVioletRed', 'el     : ' + this.$el)
    console.log(this.$el)
    console.log('%c%s', 'color:MediumVioletRed', 'data   : ' + this.$data)
    console.log(document.getElementById('app').innerHTML)
    console.log('%c%s', 'color:MediumVioletRed', 'msg: ' + this.msg)
    console.groupEnd()
  }
}
</script>

beforeCreatecreated

beforeCreate:在实例初始化完成时,被执行

created:在初始化结束之后会再初始化一些外部注入和一些双向绑定相关的事情时,被执行

这两个钩子函数执行完之后,初始化基本完成了。

beforeCreate阶段,eldata都没有被挂载;而在created阶段,el还没被挂在,但data已经被挂载了,如下图所示:

这里el为啥没有被挂载呢?

看上图,在created执行完毕后,它会询问一个条件:你这个Vue实例里是否有el这个选项。

如果有就又会询问是否有template这个选项:

  • 如果没有template就会走右侧的分支,

    • 如果这个实例没有template,就会将el这个根节点当做模版,来进行渲染
  • 如果有template就会走左侧的分支

    • template作为模版去渲染

beforeMountmounted

beforeMount:执行时,页面还没有被渲染
mounted:执行时,页面已经被渲染了

从图中也可以看出,在beforeMount执行时,el还没有被挂在;当mounted执行时,el被挂载到页面了。

beforeUpdateupdated

beforeUpdate:数据被改变,还没渲染之前会被执行

updated:数据被改变,渲染完成后会被执行

这张图中有个奇怪的现象,为什么在beforeUpdateupdated两个钩子函数中,elmsg都是一样呢?beforeUpdate执行是不应该是老数据嘛,怎么这里也是最新的数据了?

因为这里的el是虚拟dom,不是真实的dom,和data都是对象,在加上console.log这里是个异步操作,当你点开console.log时,其实代码早就跑完了,数据已经是最新的了,所以就会看到在这两个函数中输出结果是一样的了。

可以用document.getElementById('app').innerHTML获取真实的Dom结构,这时我们就可以看到这两处不一样的地方了。

beforeDestroydestroyed

调用vm.$destroy()方法可对实例销毁

beforeDestroy:实例被销毁前被执行

destroyed:实例被销毁后被执行

activateddeactivated

使用keep-alive标签后,会有两个生命周期函数分别是:activateddeactivated

activated:页面展示的时候被执行

deactivated:页面被隐藏或者页面即将被替换成新的页面时被执行

总结

created:挂载之前需要做的一些事情可以在放在这里面,比如页面加载时loading动画

mounted:向后端发请求,可以放在这个函数中。

这两个钩子函数使用时机重叠部分很多,反正是怎么方便怎么来就是了。

参考资源

  1. Vue2.0 探索之路——生命周期和钩子函数的一些理解
  2. vue2 为什么beforeUpdate时的$el 和$data与updated时的一样
  3. JavaScript:钩子函数与回调函数的区别

相关文章:

  • 关于AWS的Firecracker,技术人应该知道的十件事
  • spring boot 2.0单元测试
  • ansible API 常用模块
  • 追踪解析 FutureTask 源码
  • 再次简单明了总结flex布局,一看就懂...
  • 倒计时3天,公链黑马YOUChain正式开启节点测试
  • 那些被忽略的 JavaScript 数组方法细节
  • 如何抓住下一波零售风口?看RPA玩转零售自动化
  • 可达性分析算法
  • MySQL的sql语言分类DML、DQL、DDL、DCL、
  • 在IIS上部署ASP.NET Core项目出现错误 500.19
  • poj 1088(dfs+dp)
  • flutter的key在widget list的作用以及必要性
  • 深入 Nginx 之配置篇
  • 干货!手把手教你打造自己的seo生态资源,让排名不在是梦想
  • [LeetCode] Wiggle Sort
  • 《剑指offer》分解让复杂问题更简单
  • 2017届校招提前批面试回顾
  • CSS盒模型深入
  • IE报vuex requires a Promise polyfill in this browser问题解决
  • Java教程_软件开发基础
  • laravel 用artisan创建自己的模板
  • Linux下的乱码问题
  • Netty源码解析1-Buffer
  • Vue--数据传输
  • 对象引论
  • 二维平面内的碰撞检测【一】
  • 猴子数据域名防封接口降低小说被封的风险
  • 浅谈Kotlin实战篇之自定义View图片圆角简单应用(一)
  • 如何使用 OAuth 2.0 将 LinkedIn 集成入 iOS 应用
  • 小而合理的前端理论:rscss和rsjs
  • CMake 入门1/5:基于阿里云 ECS搭建体验环境
  • LevelDB 入门 —— 全面了解 LevelDB 的功能特性
  • ​补​充​经​纬​恒​润​一​面​
  • ###51单片机学习(2)-----如何通过C语言运用延时函数设计LED流水灯
  • #100天计划# 2013年9月29日
  • (12)目标检测_SSD基于pytorch搭建代码
  • (13):Silverlight 2 数据与通信之WebRequest
  • (32位汇编 五)mov/add/sub/and/or/xor/not
  • (33)STM32——485实验笔记
  • (C++)栈的链式存储结构(出栈、入栈、判空、遍历、销毁)(数据结构与算法)
  • (MonoGame从入门到放弃-1) MonoGame环境搭建
  • (非本人原创)史记·柴静列传(r4笔记第65天)
  • (附源码)springboot建达集团公司平台 毕业设计 141538
  • (数位dp) 算法竞赛入门到进阶 书本题集
  • (原创) cocos2dx使用Curl连接网络(客户端)
  • (原創) 如何解决make kernel时『clock skew detected』的warning? (OS) (Linux)
  • (转)Android中使用ormlite实现持久化(一)--HelloOrmLite
  • (转)大型网站的系统架构
  • .apk 成为历史!
  • .NET Core 网络数据采集 -- 使用AngleSharp做html解析
  • .net FrameWork简介,数组,枚举
  • .net wcf memory gates checking failed
  • .NET 使用 ILMerge 合并多个程序集,避免引入额外的依赖
  • .NET 中各种混淆(Obfuscation)的含义、原理、实际效果和不同级别的差异(使用 SmartAssembly)