• 猿创征文 |《深入浅出Vue.js》打卡Day6


    第14章 生命周期

    每个Vue.js实例在创建时都要经历一系列初始化,例如设置数据监听,编译模板,将实例挂载到DOM并在数据变化时更新DOM等。同时,也会有运行一些叫做生命周期钩子的函数,这给了我们在不同阶段添加自定义代码的机会。

    14.1 生命周期图示

    在这里插入图片描述
    Vue.js可以分为4个阶段:初始化阶段、模板编译阶段、挂载阶段、卸载阶段。

    14.1.1 初始化阶段

    new Vue() created之间的阶段叫做初始化阶段,这个阶段主要目的就是在Vue.js实例上初始化一些属性,事件以及响应式数据,如propsmethodsdatacomputedwatchprovideinject等。

    Vue.js的整个生命周期中,初始化实例属性是第一步,需要实例化的属性既有Vue.js内部需要用到的属性,也有提供给外部使用的属性。以$开头的属性是提供给用户使用的外部属性,以_开头的属性是提供给内部使用的内部属性

    初始化 provie/inject

    injectprovide选项需要一起使用,它们运行祖先组件向其所有子孙后代注入依赖,并在其上下游关系成立的时间里始终生效(不论组件层次有多深)
    在这里插入图片描述

    初始化 props

    props的实现原理大体上是这样的:父组件提供数据,子组件通过props字段选择自己需要哪些内容,Vue.js内部通过子组件的props选项将需要的数据筛选出来之后添加到子组件的上下文中。

    初始化 methods

    初始化methods时,只需要循环选项中的methods对象,并将每个属性依次挂载到vm上即可。

    初始化 data

    简单来说,data中的数据最终会保存到vm. data中。然后在vm上设置一个代理,使得通过vm.x可以访问到vm._data 中的×属性。最后由于这些数据并不是响应式数据,所以需要调用observe函数将data转换成响应式数据。于是,data就完成了初始化。

    初始化 computed

    我们知道计算属性的结果会被缓存,且只有在计算属性所依赖的响应式属性或者说计算属性的返回值发生变化时才会重新计算。那么,如何知道计算属性的返回值是否发生了变化?

    这其实是结合watcherdirty属性来分辨的:当dirty属性为true时,说明需要重新计算“计算属性”的返回值;当dirty属性为false时,说明计算属性的值并没有变,不需要重新计算。

    当计算属性中的内容发生变化后,计算属性的watcher与组件的watcher都会得到通知。计算属性的watcher 会将自己的dirty属性设置为true,当下一次读取计算属性时,就会重新计算一次值。然后组件的watcher也会得到通知,从而执行render 函数进行重新渲染的操作。由于要重新执行render函数,所以会重新读取计算属性的值,这时候计算属性的watcher已经把自己的dirty属性设置为true,所以会重新计算一次计算属性的值,用于本次渲染。

    这导致一个问题:如果计算属性中用到的状态发生了变化,但最终计算属性的返回值并没有变,这是计算属性依然会认为自己的返回值变了,组件也会重新走一遍渲染流程,只不过最终由于虚拟DOMDiff中发现没有变化,所有在视觉上并不会发现UI有变化,其实渲染函数会被执行。

    解决方法:组件的Watcher不再观察数据的变化,只是观察计算属性的Watcher,然后计算属性主动通知组件是否需要进行渲染操作。

    初始化 watch

    初始化的最后一步是初始化watch
    只需要循环watch选项,将对象中的每一项依次调用vm.$watch方法来观察表达式或computedVue.js实例上的变化即可。

    14.1.2 模板编译阶段

    created钩子函数与beforeMount钩子函数之间的阶段是模板编译阶段,这个阶段主要目的是将模板编译为渲染函数。

    14.1.3 挂载阶段

    beforeMount钩子函数到mounted钩子函数之间是挂载阶段。
    这个阶段,Vue.js会将其实例挂载到DOM元素上,通俗地讲,就是将模板渲染到指定DOM元素中。在挂载的过程中,Vue.js会开启Watcher来持续追踪依赖的变化,当数据(状态)发生变化时,Watcher会通知虚拟DOM重新渲染视图,并且会在渲染视图前触发beforeUpdate钩子函数,渲染完毕后触发updated钩子函数。

    14.1.4 卸载阶段

    调用vm.$destroy 方法后,Vue.js的生命周期会进入卸载阶段。在这个阶段,Vue.js会将自身从父组件中删除,取消实例上所有依赖的追踪并且移除所有的事件监听器。

    14.2 从源码角度了解生命周期

    new Vue() 被调用时发生了什么

    new Vue() 之前,首先进行安全检测,在非生产环境下,如果没有使用new来调用Vue,则会在控制台抛出错误警告我们:Vue是构造函数,应该使用new关键字来调用,然后调用this._init(options)来执行生命周期的初始化流程(在生命周期钩子beforeCreate被触发之前执行了initLifecycleinitEvents initRender。在初始化的过程中,首先初始化事件与属性.然后触发生命周期钩子beforeCreate。随后初始化 provide/inject和状态,这里的状态指的是props、methods、data、computed 以及 watcha接着触发生命周期钩子created。最后,判断用户是否在参数中提供了el选项,如果是,则调用vm .$mount方法,进入后面的生命周期阶段。)
    在这里插入图片描述

    14.3 errorCaptured 与错误处理

    errorCaptured钩子函数的作用是捕获来自子孙组件的错误,此钩子函数会收到三个参数:错误对象发生错误的组件实例以及一个包含错误来源信息的字符串然后此钩子函数可以返回false,阻止该错误继续向上传播。

    其传播规则如下:
    1、默认情况下,如果全局的 config.errorHandler被定义,那么所有的错误都会发送给它,这样这些错误可以在单个位置报告给分析服务。
    2、如果一个组件继承的链路或其父级从属链路中存在多个errorCaptured钩子,则它们将会被相同的错误逐个唤起。
    3、如果errorCaptured钩子函数自身抛出了一个错误,则这个新错误和原本被捕获的错误都会发送给全局的config.errorHandler
    4、一个errorCaptured钩于函数能够返回false来阻止错误继续向上传播。

    errorCaptured钩子函数触发:
    Vue.js在调用这些函数时,会使用try……catch语句来捕获有可能发生的错误。当错误发生并且被try……catch语句捕获后,Vue.js会使用handleError函数来处理错误,该函数会依次触发父组件链路上的每一个父组件中定义的errorCaptured钩子函数。也就是说errorCaptured的错误传播是在handleError函数中实现的。

    如有写的不对的地方,欢迎来讨论。

    在这里插入图片描述

  • 相关阅读:
    HTML5期末大作业——HTML+CSS+JavaScript平遥古城旅游景点介绍(6页)
    archlinux的开源与自由定制
    java计算机毕业设计商场后台管理系统源码+系统+数据库+lw文档+mybatis+运行部署
    Synchronized 和 lock的区别?+悲观锁和乐观锁+可重入锁【Interview】
    关于vba代码运行时错误1004 应用程序定义或对象定义错误问题
    实战EDA电子设计自动化经典入门模型VHDL代码编写(含代码解释)中上篇--2-4译码器 信号十分频
    【NI国产替代】高速数据采集模块,最大采样率为 125 Msps,支持 FPGA 定制化
    257. 二叉树的所有路径
    Flink系列之Flink中RestartStrategy重启策略和FailoverStrategy故障转移策略
    VUE+TS使用elementUI的el-checkbox双重v-for循环做勾选
  • 原文地址:https://blog.csdn.net/qq_48701993/article/details/126812809