详解Vue2中的生命周期与钩子函数(Vue面试官必问系列)

2023-05-16

目录

一、概念

二、生命周期过程

1、流程图示

2、三阶段

三、钩子函数详解

1. beforeCreate() 创建前

2. created()创建后

3. beforeMount() 挂载前

4. mounted()挂载完成

5. beforeUpdate() 更新前

6. updated() 更新后

7. beforeDestroy() 销毁前

8. destroyed() 销毁完成

三、生命周期流程与各流程详解图示(非常实用)

四、父子组件钩子函数在三个阶段的代码执行顺序


一、概念

每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数。生命周期钩子的 this 上下文指向调用它的 Vue 实例。

钩子函数是用于描述一个组件实例从引入到退出的全过程中的某个过程,整个过程成为生命周期

也就是在如下代码中,new一个Vue实例的这几行代码,所执行的全过程。

new Vue({
  el: '#app',
  router,
  store,
  render: h => h(App)
})

二、生命周期过程

1、流程图示

2、三阶段

组件的生命周期共分为三个阶段:挂载阶段、更新阶段、销毁阶段。

每个阶段对应的钩子函数分别为:

  1. 挂载阶段:beforeCreate、created、beforeMount、mounted
  2. 更新阶段:beforeUpdate、updated
  3. 销毁阶段:beforeDestroy、destroyed

即首次创建实例过程中,只执行四个生命周期钩子,beforeCreate、created、beforeMount、mounted,执行顺序与生命周期图一致,beforeUpdate与updated是在数据更新时候执行,而beforeDestroy与destroyed是在实例销毁的时候执行。

三、钩子函数详解

new (创建)一个Vue实例,会调用初始化 init 函数,初始化事件(如$once)和生命周期,注意此时数据代理并没有实现。此时,无法通过Vue实例来访问data中的数据、computed、watch、methods等中的方法。

1. beforeCreate() 创建前

beforeCreate() 创建前,指的是数据监测和数据代理创建之前。该钩子函数执行后,初始化数据,并通过Object.defineProperty()和给组件实例配置watcher观察者实例(发布-订阅者模式),实现数据监测与数据代理。

案例验证:

new Vue({
  el:"#app",
  render: h => h(App),
  data() {
    return {
      demo:"hello world!"
    }
  },
  beforeCreate(){
    console.log("****beforeCreate()执行阶段*****")
    console.log("demo 的值是:",this.demo)
    console.log("el 的值是:",this.$el)
  }
})

打印结果如下:证明此时,data中的数据与el还未初始化,无法通过Vue实例来访问data中的数据、computed、watch、methods等中的方法。

2. created()创建后

created()创建后,指的是数据监测和数据代理创建之后。该钩子函数执行后,实例创建完成,实例已完成以下配置:数据观测、属性和方法的运算,watch/event事件回调,完成了data 数据的初始化,可以访问data、computed、watch、methods上的方法和数据。但是,未挂载到DOM,不能访问到el属性,el属性,ref属性内容为空。

补充:ref属性介绍

1. 被用来给元素或子组件注册引用信息(id的替代者)
2. 应用在html标签上获取的是真实DOM元素,应用在组件标签上是组件实例对象(vc)
3. 使用方式:
   1. 打标识:<h1 ref="xxx">.....</h1> 或 <School ref="xxx"></School>
   2. 获取:this.$refs.xxx

案例验证:

new Vue({
  el:"#app",
  render: h => h(App),
  data() {
    return {
      demo:"hello world!"
    }
  },
  beforeCreate(){
    console.log("****beforeCreate()执行阶段*****")
    console.log("demo 的值是:",this.demo)
    console.log("el 的值是:",this.$el)
  },
  created(){
    console.log("****created()执行阶段*****")
    console.log(this)
    console.log("demo 的值是:",this.demo)
    console.log("el 的值是:",this.$el);
    debugger;
  }
})

 打印结果如下:证明此时,data 数据的初始化完成,数据监测和数据代理创建,el目前不可见

这个钩子函数比较重要,这个时候类似于人类的婴儿刚刚出生,这时候,需要给婴儿做一些检查。所以,在这个时候,可以调用methods中的方法,改变data中的数据且变化可以响应在页面上,获取computed中的计算属性等等,也可以在这里发ajax请求等(给婴儿的检查就类似调用方法,发送请求等)。

created执行完毕后,进行下面的环节:

在分析这个图示之前,我们先展示new Vue实例的两种方式:

方式一:含有el配置项

new Vue({
  el: '#app', //含有el配置项
  router,
  store,
  render: h => h(App)
})

方式二:无 el 配置项,调用$mount进行挂载

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

现在分析图示:new Vue实例时,是否有 el 配置项,假如采用方式一创建Vue实例,则有 el 配置项,则进一步判断是否有 template 配置项;假如采用方式二创建Vue实例,则无 el 配置项,当执行.$mount('#app')时,则进一步判断是否有 template 配置项。

有 template 配置项时,将template模板转换成render函数(在此之前判断当前是否有render函数,如果有,则会直接去渲染当前的render函数,如果没有则查找是否有template模板),如果没有template,将直接获取到的el(也就是我们常见的#app)的outerHTML的内容编译成template,然后在将这个template转换成render函数。

在上述图示的环节中,就是Vue解析模板template的过程,此时,在内存中生成虚拟DOM,但是页面不能显示解析好的内容。

3. beforeMount() 挂载前

beforeMount() 执行时,页面呈现的是未经Vue编译的DOM结构,所有对DOM的操作,最终都不奏效。

案例验证:

new Vue({
  el:"#app",
  render: h => h(App),
  data() {
    return {
      demo:"hello world!"
    }
  },
  beforeCreate(){
    console.log("****beforeCreate()执行阶段*****")
    console.log("demo 的值是:",this.demo)
    console.log("el 的值是:",this.$el)
  },
  created(){
    console.log("****created()执行阶段*****")
    console.log("demo 的值是:",this.demo)
    console.log("el 的值是:",this.$el)
  },
  beforeMount() {
    console.log("****beforeMount()执行阶段*****")
    debugger
  },
})

断点放在在beforeMount()执行阶段,结果如下:

 从下图可以看到,页面呈现的是未经Vue编译的DOM结构

 接下来的环节:

这个环节,将内存中的虚拟DOM,转换成真实DOM,插入到页面中,注意,$el中也存储了真实DOM,并不是直接仅仅插入到页面中。这个环节为后续的diff算法提供了基础。

案例验证:将断点放在mounted()执行阶段

new Vue({
  el:"#app",
  render: h => h(App),
  data() {
    return {
      demo:"hello world!"
    }
  },
  beforeCreate(){
    console.log("****beforeCreate()执行阶段*****")
    console.log("demo 的值是:",this.demo)
    console.log("el 的值是:",this.$el)
  },
  created(){
    console.log("****created()执行阶段*****")
    console.log("demo 的值是:",this.demo)
    console.log("el 的值是:",this.$el)
  },
  beforeMount() {
    console.log("****beforeMount()执行阶段*****")
  },
  mounted(){
    console.log("****mounted()执行阶段*****")
    debugger
  }
})

 此时页面上呈现的是经过Vue编译的内容,如下:

4. mounted()挂载完成

此时,页面上呈现的是经过Vue编译的DOM;对DOM的操作均有效(但是要尽量避免操作DOM)。

至此,初始化阶段全部完成。一般在此执行:开启定时器,发送网络请求,订阅消息,绑定自定义事件等初始化操作。

5. beforeUpdate() 更新前

当数据发生变化,执行beforeUpdate()钩子函数,此时,内存中数据是新的,但是页面是旧的,也就是,在这个钩子函数中,页面和数据不同步

案例验证:

data() {
    return {
      n:1
    }
},
  
methods: {
    updateN(){
      this.n += 1
    }
},
beforeUpdate(){
    console.log("****beforeUpdate()执行阶段*****")
    console.log("n的值为",this.n)
    debugger
},

当点击按钮,内存中的数据发生变化,n=2,但是页面上n仍然为1: 

下图所示的环节:

beforeUpdate执行结束之后,重新生成一个新的虚拟dom(Vnode),用它和原来的Vnode做比较(diff算法)patch指的就是这个比较的过程,更新render函数中的数据,之后将render函数渲染成真实dom,完成了 Model --> View 的更新。

6. updated() 更新后

此时:内存中数据是新的,但是页面是新的,也就是,在这个钩子函数中,页面和数据保持同步

beforeUpdate(){
    console.log("****beforeUpdate()执行阶段*****")
    console.log("n的值为",this.n)
},
updated(){
    console.log("****updated()执行阶段*****")
    console.log("n的值为",this.n)
    debugger
}

代码的执行结果如下: 

接下来的环节: 当调用$.destroy()时,会完全销毁实例

7. beforeDestroy() 销毁前

在销毁前,实例中所有的data、methods、computed、指令等,都处于可用状态在此阶段,一般进行:关闭定时器、取消订阅消息解绑自定义事件等收尾工作。

接下来的环节,移除监视、所有的子组件、(自定义)事件的监听器 

8. destroyed() 销毁完成

销毁完成后,执行destroyed。该实例的生命周期结束。

三、生命周期流程与各流程详解图示(非常实用)

* 注:该图片来源《尚硅谷Vue技术全家桶(天禹老师主讲)的上课资料》

四、父子组件钩子函数在三个阶段的代码执行顺序


挂载:父亲created> 子created > 子mounted> 父亲mounted>
更新:父亲beforeUpdate > 子beforeUpdated > 子updated > 父亲updated
销毁:父亲beforeDestroy> 子beforeDestroy > 子destroyed> 父destroyed


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

详解Vue2中的生命周期与钩子函数(Vue面试官必问系列) 的相关文章

  • vue3.0删除node_modules 无用的依赖

    安装插件 npm i depcheck 查看无用的插件 npx depcheck 对应删除 npm uninstall kd layout
  • Element Plus 配置自动按需引入后,手动引入组件,组件样式丢失

    起因 最近在尝试使用 Element Plus 写一些简单的页面 跟着官方文档走配置了自动按需引入 npm install D unplugin vue components unplugin auto import vite config
  • 生产环境的域名地址与后端给的接口地址不一样时的配置(vue)

    1 找到 config dev env js 文件 module exports merge prodEnv NODE ENV development API ROOT http com 本地开发时用的域名 2 找到 config prod
  • vue3使用import.meta.env在vite.config.ts下使用env环境变量的方法

    vue3使用import meta env在vite config ts下使用env环境变量的方法 编程一枚的博客 CSDN博客
  • Vue + Element UI 前端篇(十一):第三方图标库

    Vue Element UI 实现权限管理系统 前端篇 十一 第三方图标库 使用第三方图标库 用过Elment的同鞋都知道 Element UI提供的字体图符少之又少 实在是不够用啊 幸好现在有不少丰富的第三方图标库可用 引入也不会很麻烦
  • Vue2运行报错SyntaxError: Cannot use import statement outside a module

    问题描述 像配置vue3那样配置vue config js的路径代理 代替src后 报错 语法错误 不能在模块外部使用导入语句 原因 模块语法一个是CommonJS module 一个是 ES6 module vue config js里的
  • ip正则表达式

    var Sip rule value callback gt if 2 5 0 5 0 4 d 0 1 d 1 2 2 5 0 5 0 4 d 0 1 d 1 2 3 test value false callback new Error
  • 值得收藏的UmiJS 教程

    点击上方关注 前端技术江湖 一起学习 天天进步 前言 网上的umi教程是真的少 很多人都只写了一点点 很多水文 所以打算自己写一篇 自己搭建umi 并封装了一下常用的功能 并用到公司实际项目中 umi介绍 Umi 是什么 Umi 中文可发音
  • 上拉加载原理

    实现思路 之前写过一篇触底加载 经过一番苦学钻研 优化一下 样式方面 滚动区域是给固定高度 设置 overflow y auto 来实现 接下来看看js方面的实现 其实也很简单 触发的条件是 可视高度 滚动距离 gt 实际高度 例子我会使用
  • vue发展历史简介

    基本介绍 Vue 是一套用于构建用户界面的 渐进式框架 与其它大型框架不同的是 Vue 被设计为可以自底向上逐层应用 最初它不过是个人项目 时至今日 已成为全世界三大前端框架之一 github 上拥有 17 8万 Star 领先于 Reac
  • Vue与TypeScript的完美结合

    前言 TypeScript 是 JS类型的超集 并支持了泛型 类型 命名空间 枚举等特性 弥补了 JS 在大型应用开发中的不足 在我们自己单独学习 TS时 时常感觉很多知识点还是比较好理解的 但要和框架结合的话 感觉就有点糟 因为我使用Vu
  • Vue学习之watch侦听器:案例实现翻译功能

    watch侦听器 作用 监视数据的变化 当数据发生变化时 执行一些业务逻辑或者是异步操作 执行的场景例如在线翻译 当文本区域的内容发生变化时 会发生翻译内容的同时更新 语法 简单的写法 简单数据类型 可以直接的进行监听 完整的写法 添加额外
  • 黑豹程序员-自定义表单实现门户自定制

    功能 用户可以实现欢迎页面自己定制 数据由数据库表进行维护 原理 页面利用div进行布局 拖动div记录其坐标 并写库 页面加载时从数据库表中读取div坐标和数据即可 效果图
  • 基于vue2+海康威视web开发包3.2 无插件版本开发的监控系统

    文章目录 前言 一 插件准备 二 使用步骤 前言 项目最终效果为 可以预览 并且可以使用云台控制 购买的海康威视摄像头必须可以开启websocket 一 插件准备 插件下载地址 下载WEB无插件开发包V3 2 并加入到vue项目中 下载后解
  • Vue3+Echarts:堆积柱状图的绘制

    一 需求 在Vue3项目中 想用Echarts来绘制堆积柱状图 去展示最近一周APP在不同渠道的登录人数 效果如下 二 实现 关于Echarts的下载安装以及图表的样式设计 此处不展开 1 Templates部分
  • 执行tsc -v命令后报错‘tsc‘ 不是内部或外部命令,也不是可运行的程序或批处理文件。怎样解决?

    分析 tsc v 这个命令主要是查看typescript编译器的版本号的 也可以用于检查typescript是否安装好了 是否正常 1 如果没有安装的话 就去安装 可以使用 npm ls typescript 查看本地是否安装typescr
  • 拓展:vue 父组件调用子组件方法ref(且父组件可通过ref调用的方法传值给子组件)

    1 ref被用来给元素或子组件注册引用信息 引用信息将会注册在父组件的 refs对象上 一 ref被用来给元素或子组件注册引用信息 引用信息将会注册在父组件的 refs对象上 div class formBtn fl 111 div div
  • vue项目日期处理day.js

    dayjs安装 1 npm 安装 npm install dayjs save 2 项目使用 import dayjs from dayjs ES 2015 dayjs format 使用介绍 1 秒 获取或设置秒 接受0到59的数字 如果
  • vue的组件

    在Vue中 组件是可复用的代码块 用于构建用户界面 Vue的组件系统允许您将界面拆分为独立的 可重复使用的部件 提供了更好的代码组织和复用性 以下是在Vue中创建组件的基本步骤 创建一个组件实例 可以使用Vue extend 方法创建一个V
  • 黑豹程序员-字符串中查找出重复的字符串

    Collections frequency codeList element 字符串element 在codeList集合中重复的次数 List

随机推荐