杂谈:created中两次数据修改,会触发几次页面更新?

news2024/9/30 19:40:25

面试题:created生命周期中两次修改数据,会触发几次页面更新?

一、同步的

先举个简单的同步的例子:

new Vue({el: "#app",template: `<div><div>{{count}}</div></div>`,data() {return {count: 1,}},created() {this.count = 2;this.count = 3;},
}); 

created生命周期中,通过this.count = 2this.count = 3的方式将this.count重新赋值。

这里直接抛出答案:渲染一次。


为什么?

这个与数据的响应式处理有关,先看响应式处理的逻辑:

export function defineReactive (obj: Object,key: string,val: any,customSetter?: ?Function,shallow?: boolean
) {// 重点:创建一个发布者实例const dep = new Dep()const property = Object.getOwnPropertyDescriptor(obj, key)if (property && property.configurable === false) {return}// cater for pre-defined getter/settersconst getter = property && property.getconst setter = property && property.setif ((!getter || setter) && arguments.length === 2) {val = obj[key]}let childOb = !shallow && observe(val)Object.defineProperty(obj, key, {enumerable: true,configurable: true,get: function reactiveGetter () {const value = getter ? getter.call(obj) : valif (Dep.target) {// 重点:进行当前正在计算的渲染Watcher的收集dep.depend()if (childOb) {childOb.dep.depend()if (Array.isArray(value)) {dependArray(value)}}}return value},set: function reactiveSetter (newVal) {const value = getter ? getter.call(obj) : val/* eslint-disable no-self-compare */if (newVal === value || (newVal !== newVal && value !== value)) {return}/* eslint-enable no-self-compare */if (process.env.NODE_ENV !== 'production' && customSetter) {customSetter()}// #7981: for accessor properties without setterif (getter && !setter) returnif (setter) {setter.call(obj, newVal)} else {val = newVal}childOb = !shallow && observe(newVal)// 重点:当数据发生变化时,发布者实例dep会通知收集到的watcher进行更新dep.notify()}})
} 

在数据响应式处理阶段,会实例化一个发布者dep,并且通过Object.defineProperty的方式为当前数据定义getset函数。在生成虚拟vNode的阶段,会触发get函数中会进行当前正在计算的渲染Watcher的收集,此时,发布者depsubs中会多一个渲染Watcher实例。在数据发生变化的时候,会触发set函数,通知发布者depsubs中的watcher进行更新。

至于数据修改会触发几次更新,就与当前发布者depsubs中收集了几次渲染watcher有关了,再看watcher收集和created执行之间的顺序:

Vue.prototype._init = function (options) {// ...initState(vm);// ...callHook(vm, 'created');// ...if (vm.$options.el) {vm.$mount(vm.$options.el);}
} 

我们知道在initState(vm)阶段对数据进行响应式处理,但是此时发布者depsubs还是空数组。当执行callHook(vm, 'created')的时候,会执行this.count = 2this.count = 3的逻辑,也的确会触发set函数中的dep.notify通知收集到的watcher进行更新。但是,此时depsubs是空数组,相当于啥也没做。

只有在vm.$mount(vm.$options.el)执行过程中,生成虚拟vNode的时候才会进行渲染Watcher收集,此时,depsubs才不为空。最终,通过vm.$mount(vm.$options.el)进行了页面的一次渲染,并未因为this.count=2或者this.count=3而触发多余的页面更新。

简言之,就是created钩子函数内的逻辑的执行是在渲染watcher收集之前执行的,所以未引起因为数据变化而导致的页面更新。

二、异步的

同步的场景说完了,我们再举个异步的例子:

new Vue({el: "#app",template: `<div><div>{{count}}</div></div>`,data() {return {count: 1,}},created() {setTimeout(() => {this.count = 2;}, 0)setTimeout(() => {this.count = 3;}, 0)},
}); 

created生命周期中,通过异步的方式执行this.count = 2this.count = 3的方式将this.count重新赋值。

这里直接抛出答案:首次渲染一次,因为数据变化导致的页面更新两次。


为什么?

这个就与eventLoop事件循环机制有关了,我们知道javascript是一个单线程执行的语言,当我们通过new Vue实例化的过程中,会执行初始化方法this._init方法,开始了Vue底层的处理逻辑。当遇到setTimeout异步操作时,会将其推入到异步队列中去,等待当前同步任务执行完以后再去异步队列中取出队首元素进行执行。

当前例子中,在initState(vm)阶段对数据进行响应式处理。当执行callHook(vm, 'created')的时候,会将this.count = 2this.count = 3的逻辑推入到异步队列等待执行。继续执行vm.$mount(vm.$options.el)的过程中会去生成虚拟vNode,进而触发get函数的渲染Watcher收集,此时,depsubs中就有了一个渲染watcher

等首次页面渲染完成以后,会去执行this.count=2的逻辑,数据的修改会触发set函数中的dep.notify,此时发布者depsubs不为空,会引起页面的更新。同理,this.count=3会再次引起页面数据的更新。也就是说,首次渲染一次,因为this.count=2this.count=3还会导致页面更新两次。

三、附加

如果我改变的值和data中定义的值一致呢?

new Vue({el: "#app",template: `<div><div>{{count}}</div></div>`,data() {return {count: 1,}},created() {setTimeout(() => {this.count = 1;}, 0)},
}); 

这个时候,在触发set的逻辑中,会当执行到if (newVal === value || (newVal !== newVal && value !== value)) { return }的逻辑,不会再执行到dep.notify,这种场景下数据的数据也不会引起页面的再次更新。

总结

从生命周期created和页面渲染的先后顺序,Object.defineProperty触发getset函数的机理,以及eventLoop事件循环机制入手,去分析created中两次数据修改会触发几次页面更新的问题就会清晰很多。

最后

整理了75个JS高频面试题,并给出了答案和解析,基本上可以保证你能应付面试官关于JS的提问。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[架构之路-124]-《软考-系统架构设计师》-操作系统-3-操作系统原理 - IO设备、微内核、嵌入式系统

第11章 操作系统第5节 设备管理/文件管理&#xff1a;IO5.1 文件管理5.2 IO设备管理&#xff08;内存与IO设备之间&#xff09;数据传输控制是指如何在内存和IO硬件设备之间传输数据&#xff0c;即&#xff1a;设备何时空闲&#xff1f;设备何时完成数据的传输&#xff1f;SPOO…

vue实战-深入响应式数据原理

本文将带大家快速过一遍Vue数据响应式原理&#xff0c;解析源码&#xff0c;学习设计思路&#xff0c;循序渐进。 数据初始化 _init 在我们执行new Vue创建实例时&#xff0c;会调用如下构造函数&#xff0c;在该函数内部调用this._init(options)。 import { initMixin } f…

代码随想录算法训练营第一天| 704. 二分查找、27. 移除元素

Leetcode 704 二分查找题目链接&#xff1a;704二分查找介绍给定一个 n 个元素有序的&#xff08;升序&#xff09;整型数组 nums 和一个目标值 target &#xff0c;写一个函数搜索 nums 中的 target&#xff0c;如果目标值存在返回下标&#xff0c;否则返回 -1。思路先看看一个…

MyBatis源码分析(三)SqlSession的执行主流程

文章目录一、熟悉主要接口二、SqlSession的获取1、通过数据源获取SqlSession三、Mapper的获取与代理1、从SqlSession获取Mapper2、执行Mapper方法前准备逻辑3、SqlCommand的创建4、构造MethodSignature四、执行Mapper的核心方法1、执行Mapper的方法逻辑五、简单SELECT处理过程1…

【蓝桥杯试题】 递归实现指数型枚举例题

&#x1f483;&#x1f3fc; 本人简介&#xff1a;男 &#x1f476;&#x1f3fc; 年龄&#xff1a;18 &#x1f91e; 作者&#xff1a;那就叫我亮亮叭 &#x1f4d5; 专栏&#xff1a;蓝桥杯试题 文章目录1. 题目描述2. 思路解释2.1 时间复杂度2.2 递归3. 代码展示最后&#x…

超级简单又功能强大还免费的电路仿真软件

设计电路的时候经常需要进行一些电路仿真。常用的仿真软件很多&#xff0c;由于大学里经常使用Multisim作为教学软件&#xff0c;所以基本上所有从事硬件开发的人都听过或者用过Multisim这个软件。这个软件最大的好处就是简单直观&#xff0c;可以在自己的PC上搭建电路并使用软…

gdb常用命令详解

gdb常用调试命令概览和说明 run命令 在默认情况下&#xff0c;gdbfilename只是attach到一个调试文件&#xff0c;并没有启动这个程序&#xff0c;我们需要输入run命令启动这个程序&#xff08;run命令被简写成r&#xff09;。如果程序已经启动&#xff0c;则再次输入 run 命令…

从面试官角度告诉你高级性能测试工程师面试必问的十大问题

目录 1、介绍下最近做过的项目&#xff0c;背景、预期指标、系统架构、场景设计及遇到的性能问题&#xff0c;定位分析及优化&#xff1b; 2、项目处于什么阶段适合性能测试介入&#xff0c;原因是什么&#xff1f; 3、性能测试场景设计要考虑哪些因素&#xff1f; 4、对于一…

SAP MM学习笔记4-在库类型都有哪些,在库类型有哪些控制点

SAP MM模块中的在库类型有3种&#xff1a; 1&#xff0c;利用可能在库 (非限制使用库存) 2&#xff0c;品质检查中在库 &#xff08;质检库存&#xff09; 3&#xff0c;保留在库&#xff08;已冻结库存&#xff09; 这3种在库标识该物料的状态&#xff0c;是否可用。 这3种…

bugku 安全加固1

js劫持 根据题目所给出的ip访问原本应该进入一个学院的二手交易网站 但是实际进入了一个博客 flag需要去除最后的斜杆 黑客首次webshell密码 利用所给的账户密码进行登录进入www目录并且进行备份 #我们对网站进行备份 cd /var/www && tar -czvf /tmp/html.tgz html …

Kubernetes之存储管理(上)

数据持久化的主要方式简介 pod是临时的&#xff0c;pod中的数据随着pod生命周期的结束也会被一起删除。 pod想实现数据持久化主要有以下几种方式&#xff1a; emptyDir&#xff1a;类似于docker run –v /xx&#xff0c;在物理机里随机产生一个目录(这个目录其实挂载的是物理…

墨天轮2022年度数据库获奖名单

2022年&#xff0c;国家相继从高位部署、省级试点布局、地市重点深入三个维度&#xff0c;颁布了多项中国数据库行业发展的利好政策。但是我们也能清晰地看到&#xff0c;中国数据库行业发展之路道阻且长&#xff0c;而道路上的“拦路虎”之一则是生态。中国数据库的发展需要多…

如何创建发布新品上市新闻稿

推出新产品对任何企业来说都是一个激动人心的时刻&#xff0c;但向潜在客户宣传并围绕您的新产品引起轰动也可能是一个挑战。最有效的方法之一就是通过发布新品上市新闻稿。精心制作的新闻稿可以帮助我们通过媒体报道、吸引并在目标受众中引起关注。下面&#xff0c;我们将讲述…

计算机组成原理4小时速成2:计算机运算方法,原码,反码,补码,移位,加法减法,乘除法

计算机组成原理4小时速成2&#xff1a;计算机运算方法&#xff0c;原码&#xff0c;反码&#xff0c;补码&#xff0c;移位&#xff0c;加法减法&#xff0c;乘除法 2022找工作是学历、能力和运气的超强结合体&#xff0c;遇到寒冬&#xff0c;大厂不招人&#xff0c;可能很多…

OpenCV入门(二)快速学会OpenCV1图像基本操作

OpenCV入门&#xff08;一&#xff09;快速学会OpenCV1图像基本操作 不讲大道理&#xff0c;直接上干货。操作起来。 众所周知&#xff0c;OpenCV 是一个跨平台的计算机视觉库, 支持多语言, 功能强大。今天就从读取图片&#xff0c;显示图片&#xff0c;输出图片信息和简单的…

记录自己遇到的关于Hashmap的面试题

一.麻烦讲述一下Hashmap的扩容原理 jdk1.8中的hashmap扩容原理 1.put流程图 首先贴一张图(图片来源于传送门&#xff09;&#xff0c;多谢大佬的美图&#xff0c;此图已经完美的描述了put的整个流程&#xff0c;我也就不想自己画了&#xff0c;嘿嘿: 2.hashmap中几个比较重…

hive临时目录清理

hive运行失败会导致临时目录无法自动清理&#xff0c;因此需要自己写脚本去进行清理 实际发现hive临时目录有两个&#xff1a; /tmp/hive/{user}/* /warehouse/tablespace//hive/**/.hive-staging_hive 分别由配置hive.exec.scratchdir和hive.exec.stagingdir决定: 要注意的…

requests---(4)发送post请求完成登录

前段时间写过一个通过cookies完成登录&#xff0c;今天我们写一篇通过post发送请求完成登录豆瓣网 模拟登录 1、首先找到豆瓣网的登录接口 打开豆瓣网站的登录接口&#xff0c;请求错误的账号密码&#xff0c;通过F12或者抓包工具找到登录接口 通过F12抓包获取到请求登录接口…

每日分享(微信社区小程序/h5/圈子论坛贴吧交友/博客/社交)

1.Java单元测试实战 高清PDF中文版 Java单元测试实战来自于作者多年来的单元测试实践&#xff0c;最初发表在阿里内网的ATA上&#xff0c;成为了很多阿里同学单元测试学习的必读文章。很多程序员认为单元测试会花费大量的时间&#xff0c;因此他们写单元测试的意愿比较低&…

【同步工具类:Semaphore】

同步工具类:Semaphore介绍源码分析构造函数acquire 获取信号量release 释放信号量业务场景代码测试结果总结介绍 官方说明: Semaphore用于限制可以访问某些资源&#xff08;物理或逻辑的&#xff09;的线程数目&#xff0c;他维护了一个许可证集合&#xff0c;有多少资源需要限…