Vue2 - 生命周期

目录

  • 1,介绍
    • 1,初次渲染
    • 2,数据改变后的重渲染
  • 2,生成周期钩子执行顺序

1,介绍

创建 vue 实例和创建组件的流程基本一样。

1,初次渲染

  1. 做一些初始化操作,主要设置一些私有属性到实例中。

  2. 运行 beforeCreate

  3. 进入注入流程,处理属性,computedmethodsdataprovideinject等,最后使用代理模式将他们挂载到实例中(为了可通过 this 访问):

// 伪代码
function Vue(options) {var data = options.data();Vue.observe(data); // 变成响应式数据var methods = options.methods;// 代理模式挂载到实例上Object.defineProperty(this, "a", {get() {return data.a;},set(val) {data.a = val;},});Object.entries(methods).forEach(([methodName, fn]) => {this[methodName] = fn.bind(this);});
}new Vue(vnode.componentOptions);
  1. 运行created

  2. 生成 render 函数,如果有配置render 函数则直接使用。没有则使用运行时编译器把模板 template 编译为 render。参考虚拟DOM的生成。

  3. 运行 beforeMount

  4. 生成真实 DOM

// 伪代码
function Vue(){// ... 其他代码var updateComponent = () => {this._update(this._render())}new Watcher(updateComponent);// ... 其他代码
}

创建一个 Watcher,传入一个函数updateComponent,该函数会运行render,把得到的vnode再传入_update函数执行。

在执行render函数的过程中,会收集所有依赖,之后依赖变化时会重新运行updateComponent函数

在执行_update函数的过程中,触发patch函数,由于目前没有旧树,因此直接为当前的虚拟dom树的每一个普通节点生成 elm 属性,即真实dom。

如果遇到组件的vnode,则会进入组件的实例化流程,该流程和创建vue实例流程基本相同,最终会把创建好的组件实例挂载到其 VNodecomponentInstance属性中,以便复用。

组件的 VNode 有2个属性:componentOptions对应传递的属性;componentInstance 对应组件实例。
对组件来说,diff 时会认为新旧2个的节点相同,所以组件实例会重用,并不会新建。如果属性变化了,给新节点的 componentOptions 重新赋值即可。

具体参考 数据响应式原理

  1. 运行 mounted

2,数据改变后的重渲染

  1. 数据变化后,所有依赖该数据的Watcher均会重新运行,这里仅考虑 updateComponent 函数对应的 Watcher

  2. Watcher会被调度器放到nextTick中运行,也就是微队列中,这样是为了避免多个依赖的数据同时改变后被多次执行

  3. 运行 beforeUpdate

  4. updateComponent函数重新执行

    在执行render函数的过程中,会去掉之前的依赖,重新收集所有依赖,将来依赖变化时会重新运行updateComponent函数

    在执行_update函数的过程中,触发patch函数,对新旧两棵树进行对比:

    • 普通html节点的对比会导致真实DOM被创建、删除、移动、更新

    • 组件节点的对比会导致组件被创建、删除、移动、更新

    当新组件需要创建时,进入实例化流程(前文中的初次渲染)。

    当旧组件需要删除时,会调用旧组件的$destroy方法删除组件,该方法会先触发beforeDestroy,然后递归调用子组件的$destroy方法,然后触发destroyed

    组件属性更新时,相当于组件的updateComponent函数被重新触发执行,进入重渲染流程,参考上面的步骤再来一遍。

  5. 运行updated

2,生成周期钩子执行顺序

示例:Vue 实例中渲染了 App.vueApp.vue 又引入了子组件A.vue

大致代码如下:

// main.js
import Vue from "vue";
import App from "./App.vue";new Vue({render: (h) => h(App),beforeCreate() {console.log("vue实例 beforeCreate");},// ...// 其他生命周期函数// ...destroyed() {console.log("vue实例 destroyed");},
}).$mount("#app");
<!-- App.vue -->
<template><div id="app"><h1>App</h1><A v-if="show" :count="count" /><button @click="count++">更新数据</button><button @click="show = !show">切换显示A组件</button></div>
</template><script>
import A from "./A.vue";export default {components: { A },data() {return {show: true,count: 0,};},beforeCreate() {console.log("App beforeCreate");},// ...// 其他生命周期函数// ...destroyed() {console.log("App destroyed");},
};
</script>
<!-- A.vue -->
<template><h1>A compnent: {{ count }}</h1>
</template><script>
export default {props: ["count"],beforeCreate() {console.log("A beforeCreate");},// ...// 其他生命周期函数// ...destroyed() {console.log("A destroyed");},
};
</script>

初次渲染:

vue实例 beforeCreate
vue实例 created
vue实例 beforeMountApp beforeCreate
App created
App beforeMountA beforeCreate
A created
A beforeMount
A mountedApp mounted
vue实例 mounted

数据改变后的重渲染:

注意,是因为修改的是响应式数据,所以会导致子组件触发更新,开始执行 beforeUpdate
所以,如果子组件没有使用父组件的响应式数据,则不会触发更新

App beforeUpdateA beforeUpdate
A updatedApp updated

当在 App.vue 通过 v-if 切换显示子组件 A.vue 时:

App beforeUpdateA beforeDestroy
A destroyedApp updated

以上。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/325426.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

十种编程语言的对比分析

在当今的软件开发领域&#xff0c;编程语言扮演着至关重要的角色。不同的编程语言各有其特点和适用场景&#xff0c;选择合适的编程语言能够提高开发效率和软件质量。本文将对十种常见的编程语言进行对比分析&#xff0c;帮助读者了解它们的优缺点和适用场景。 一、Python Pyt…

【java】期末复习知识点

简单不先于复杂&#xff0c;而是在复杂之后。 文章目录 填空题封装包主类开发过程的改变interfaceabstract class访问控制关键字继承多态object 类Java I/O(输入/输出)异常线程和进程创建线程的两种基本方法 编程题Hello World编写Swing程序&#xff0c;显示一个空白窗口 填空题…

发票信息提取v1.2.0

程序介绍 “发票信息提取”是一款用于提取电子发票的PDF、XML文件中的开票信息到excel表格的软件&#xff0c;无需联网及进行复杂配置&#xff0c;打开即用。目前支持增值税电子发票&#xff08;非数电票&#xff09;原始PDF文件&#xff0c;及数电票的XML文件。 更新内容 增加…

怎么查询网络出口IP

怎么查询自己的网络的出口IP 背景 一般跟第三方服务进行接口数据交互的时候&#xff0c;对方都会让我们提供调用接口的网络的出口IP&#xff0c;对方会把该IP地址加到对方的白名单中。这样我们才能有权限进行接口的访问。 解决办法 下面介绍三种常用的查询网络出口IP的办法…

uniapp点击跳转传对象

目录 传对象传对象传送组件接受组件 最后 传对象 传对象 传送组件 点击传给组件 <view class"dki-tit-edit" click"gotificatedit(item)">编辑 </view>gotificatedit(item){console.log(item,item);let options JSON.stringify(item);uni.…

Mysql 分割字符串,一行变多行,@rownum,mysql.help_topic

1 前言 朋友最近遇到一个比较棘手的 sql 问题&#xff0c;让我帮忙看看&#xff1a; 他有两张表 testa 和 testb &#xff0c;一个表存的日期&#xff0c;另一个表存字符串例如 2023-11-01,2023-11-02&#xff0c;如何将这两张表关联起来&#xff0c;只查 testa 表的数据&#…

分布式系统架构设计之分布式缓存技术选型

一、概述 随着互联网业务的快速发展&#xff0c;分布式系统已经成为了解决大规模并发请求、高可用性、可扩展性等问题的重要手段。在分布式系统中&#xff0c;缓存作为提高系统性能的关键技术&#xff0c;能够显著降低数据库负载、减少网络延迟、提高数据访问速度。当面对大量…

【安卓的签名和权限】

Android 编译使用哪个key签名&#xff1f; 一看Android.mk 在我们内置某个apk的时候都会带有Android.mk&#xff0c;这里面就写明了该APK使用的是什么签名&#xff0c;如&#xff1a; LOCAL_CERTIFICATE : platform表明使用的是platform签名 LOCAL_CERTIFICATE : PRESIGNED…

大模型加速库flash-attention的安装教程

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

Spark Streaming的容错性与高可用性

在实时数据处理领域&#xff0c;容错性和高可用性是至关重要的。Apache Spark Streaming是一个强大的工具&#xff0c;用于实时数据处理和分析&#xff0c;具备卓越的容错性和高可用性。本文将深入探讨Spark Streaming的容错性机制&#xff0c;以及如何实现高可用性的实时数据处…

深度学习中的自动化标签转换:对数据集所有标签做映射转换

在机器学习中&#xff0c;特别是在涉及图像识别或分类的项目中&#xff0c;标签数据的组织和准确性至关重要。本文探讨了一个旨在高效转换标签数据的 Python 脚本。该脚本在需要更新或更改类标签的场景中特别有用&#xff0c;这是正在进行的机器学习项目中的常见任务。我们将逐…

走向云原生 破局数字化

近年来&#xff0c;随着云计算概念和技术的普及&#xff0c;云原生一词也越来越热门&#xff0c;云原生成为云计算领域的新变量。行业内&#xff0c;华为、阿里巴巴、字节跳动等各个大厂都在“抢滩”云原生市场。行业外&#xff0c;云原生也逐渐出圈&#xff0c;出现在大众视野…