Vue的底层原理

news2024/11/16 13:01:35

 

如何追踪变化

当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter。

这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更。这里需要注意的是不同浏览器在控制台打印数据对象时对 getter/setter 的格式化并不同,所以建议安装 vue-devtools 来获取对检查数据更加友好的用户界面。

每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。

先通过Object.defineProperty get set拦截,每次数据更改的时候,通过set拦截,通知我们的Watcher进行触发更新,Watcher是观察者,它收集了很多跟状态相关的依赖,以及发布者和订阅者,触发这些订阅者进行调用,这样组件就会更新了。把所有的组件代码进行更新,在更新的过程中先创建一份新的虚拟dom,再对比老的虚拟dom节点,两个在对比过程中,以最小的代价找出不同,再更新到dom中。图示:

 Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个 watcher 被多次触发,只会被推入到队列中一次。



检测变化的注意事项

Vue 无法检测 property 的添加或移除。由于 Vue 会在初始化实例时对 property 执行 getter/setter 转化,所以 property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的。

var vm = new Vue({
  data:{
    a:1
  }
})

// `vm.a` 是响应式的

vm.b = 2
// `vm.b` 是非响应式的

对于数组:

Vue 不能检测以下数组的变动:

  1. 当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
  2. 当你修改数组的长度时,例如:vm.items.length = newLength

举个例子:

var vm = new Vue({
  data: {
    items: ['a', 'b', 'c']
  }
})
vm.items[1] = 'x' // 不是响应性的
vm.items.length = 2 // 不是响应性的

 

声明响应式 property

由于 Vue 不允许动态添加根级响应式 property,所以你必须在初始化实例前声明所有根级响应式 property,哪怕只是一个空值:

var vm = new Vue({
  data: {
    // 声明 message 为一个空值字符串
    message: ''
  },
  template: '<div>{{ message }}</div>'
})
// 之后设置 `message`
vm.message = 'Hello!'

如果你未在 data 选项中声明 message,Vue 将警告你渲染函数正在试图访问不存在的 property。

这样的限制在背后是有其技术原因的,它消除了在依赖项跟踪系统中的一类边界情况,也使 Vue 实例能更好地配合类型检查系统工作。但与此同时在代码可维护性方面也有一点重要的考虑:data 对象就像组件状态的结构 (schema)。提前声明所有的响应式 property,可以让组件代码在未来修改或给其他开发人员阅读时更易于理解。

Object.defineProperty有以下缺点:

1、无法监听es6的Set、Map变化;

2、无法监听Class类型的数据;

3、属性的新加或者删除也无法监听;

4、数组元素的增加和删除也无法监听;

针对Object.defineProperty的缺点,ES6 Proxy都能够完美的解决,它唯一的缺点就是,对IE不友好,所以vue3在检测到如果是使用IE的情况下(没错,IE11都不支持Proxy),会自动降级为Object.defineProperty的数据监听系统。

 

虚拟DOM树:

vdom、vnode、virtual dom、virtual node指的都是虚拟DOM。

013-key设置_哔哩哔哩_bilibili

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

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

相关文章

RK3588平台开发系列讲解(GPIO篇)配置GPIO需要了解的概念

平台内核版本安卓版本RK3588Linux 5.10Android12🚀返回专栏总目录 文章目录 一、 GPIO(通⽤输⼊输出)二、IOMUX(输⼊输出复⽤)三、PULL(端口上下拉)四、DRIVE-STRENGTH(端口驱动强度)五、 SMT(端口斯密特触发器)沉淀、分享、成长,让自己和他人都能有所收获!😄 …

SAP Gateway 在开发系统和生产系统上的缓存控制

SAP Gateway 元数据缓存可以启用和禁用&#xff0c;并且在非生产系统中默认停用。 我们推荐以下缓存设置&#xff1a; 开发系统 应该禁用 SAP Gateway 元数据缓存&#xff0c;以便始终获取最新的元数据&#xff08;默认设置&#xff09;。 OData 通道应用程序应在其模型提供…

UNIAPP实战项目笔记53 登录的前端和后端nodejs对接以及写后端接口和接口文档

UNIAPP实战项目笔记53 登录的前端和后端对接以及写后端接口和接口文档 实际案例图片 输入手机号或用户名登录页面 代码 login.vue页面 <template><view class"login"><swiper vertical"true" style"height: 100vh;"><swi…

VIM编辑器初学者用法指南——vim中无法使用冒号更改Ubuntu的输入法解决

VIM编辑器初学者用法指南一、vim打开文件&#xff1a;二、vim编辑文件&#xff1a;三、退出编辑模式四、保存文件并退出Vim编辑器Vim编辑器是Unix系统最初的编辑器&#xff0c;内置有两种操作模式:普通模式和插入模式。 普通模式&#xff1a;执行非内容编辑类的保存、退出等指令…

基于JAVA和MYSQL的图书馆座位管理系统的设计与开发

开发工具(eclipse/idea/vscode等)&#xff1a; 数据库(sqlite/mysql/sqlserver等)&#xff1a; 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a; 11-11管理员功能模块 公告管理&#xff1a;可以对馆内开放时间、意外情况或者其他安排在网上进行发布公告&#xff0c;也…

【Redis-10】Redis集群的实现原理(Redis Cluster)

Redis集群是Redis提供的分布式数据库方案&#xff0c;通过分片来进行数据共享&#xff0c;实现复制和故障转移的功能。 1. Redis集群节点 一个Redis集群由多个节点组成&#xff0c;多个节点通过命令连接&#xff0c;由独立状态转为集群状态&#xff0c;命令是cluster meet <…

C51——电动车简易防盗系统

这是电动车简易报警器信号电路 #include "reg52.h" sbit switcher P1^1; sbit D0_ON P1^2; sbit D1_OFF P1^3; sbit vibrator P1^4; void Delay3000ms() //11.0592MHz { unsigned char i, j, k; //_nop_(); i 22; j 3; k 227; …

生物素-双硫键-叠氮化物Biotin-SS-Azide CAS1620523-64-9 简介

名称&#xff1a;Biotin-SS-azide Azide-SS-biotin Azide-C2-SS-C2-biotin 是一种可降解 (cleavable) 的 ADC linker&#xff0c;可用于合成抗体偶联药物(ADC)。叠氮化物-SS-生物素是一种可裂解的生物素化试剂&#xff0c;用于使用点击化学标记含炔烃的生物分子。叠氮基与炔烃…

Mycat(2):mysql的集群搭建

MyCat的环境演示需要使用mysql集群 &#xff0c;下面先搭建mysql的环境 1 集群搭建概述 1.1 是什么 集群&#xff08;cluster&#xff09;技术是一种较新的技术&#xff0c;通过集群技术&#xff0c;可以在付出较低成本的情况下获得在性能、可靠性、灵活性方面的相对较高的收…

记一次新装的SQLServer本地无法访问的处理过程

本机新装的SQL Server连接不上, 首先尝试使用 计算机名\实例名 Windows 身份验证 的形式登录, 例如:Dell-WorkCenter\MSSQL2017 如果使用 计算机名\实例名 的形式可以登录, 但使用127.0.0.1或者本机IP地址无法登录的话, 有可能是Named Pipes 与 TCP/IP 协议没有启用, 开…

图书馆借阅数据分析系统设计与实现

开发工具(eclipse/idea/vscode等)&#xff1a; 数据库(sqlite/mysql/sqlserver等)&#xff1a; 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a; 网站前台&#xff1a;关于图书馆、帮助信息、图书资讯、图书类型、图书信息 管理员&#xff1a; 1、管理&#xff1a;关…

大数据- 初探MapReduce

一、MapReduce编程实例——词频统计实现 启动hadoop服务 1、准备数据文件 &#xff08;1&#xff09;在虚拟机上创建文本文件 创建wordcount目录&#xff0c;在里面创建words.txt文件 &#xff08;2&#xff09;上传文件到HDFS指定目录 创建/wordcount/input目录&#…

设计模式之桥接模式

bridge design pattern 桥接模式的概念、桥接模式的结构、桥接模式的优缺点、桥接模式的使用场景、桥接模式的实现示例、桥接模式的源码分析 1、桥接模式的概念 桥接模式&#xff0c;即将抽象和实现分离&#xff0c;使他们可以独立变化。它是用组合关系来代替继承关系实现的&a…

赫夫曼树 | 实战演练

&#x1f388; 作者&#xff1a;Linux猿 &#x1f388; 简介&#xff1a;CSDN博客专家&#x1f3c6;&#xff0c;华为云享专家&#x1f3c6;&#xff0c;Linux、C/C、云计算、物联网、面试、刷题、算法尽管咨询我&#xff0c;关注我&#xff0c;有问题私聊&#xff01; &…

关于动漫的HTML网页设计:期末前端web大作业——海贼王基地(6个页面)

HTML实例网页代码, 本实例适合于初学HTML的同学。该实例里面有设置了css的样式设置&#xff0c;有div的样式格局&#xff0c;这个实例比较全面&#xff0c;有助于同学的学习,本文将介绍如何通过从头开始设计个人网站并将其转换为代码的过程来实践设计。 精彩专栏推荐&#x1f4…

QT—5种标准对话框使用详解

对话框是 GUI 程序中不可或缺的组成部分。一些不适合在主窗口实现的功能组件都必须放在对话框中设置。对话框通常会是一个顶层窗口&#xff0c;出现在程序最上层&#xff0c;用于实现短期任务或者简洁的用户交互。所谓标准对话框&#xff0c;是 Qt 内置的一系列对话框&#xff…

kafka问题总结

kafka问题总结【1】Kafka 都有哪些特点&#xff1f;【2】为什么要使用 kafka&#xff0c;为什么要使用消息队列&#xff1f;【2】kafka的使用场景【3】Kafka 的设计架构【4】kafka分区的目的【5】Kafka 是如何做到消息的有序性&#xff1f;【6】Kafka 的高可靠性是怎么实现的&a…

【操作系统-总论】发展历程、体系结构、虚拟机

文章目录1 操作系统的发展历程1.1 手工操作阶段1.2 批处理阶段1.2.1 单道批处理系统&#xff08;单道程序系统&#xff09;1.2.2 多道批处理系统&#xff08;多道程序系统&#xff09;1.3 分时操作系统1.4 实时操作系统2 操作系统的体系结构3 虚拟机1 操作系统的发展历程 1.1 …

Nginx教程(3)—负载均衡

文章目录3.1 负载均衡-轮询3.2 负载均衡-加权轮询3.3 upstream指令参数3.4 使用JMeter测试集群3.5 负载均衡之IP_hash3.6 一致性hash算法3.7 Nginx控制浏览器缓存3.8 Nginx反向代理缓存Nginx教程一 Nginx教程二 3.1 负载均衡-轮询 轮询是Nginx默认使用的策略&#xff0c;轮询算…

jmeter做压测性能调优:SSL上下文切换导致SSL频繁握手【杭州多测师_王sir】【杭州多测师】...

一、问题背景在使用 JMeter 压测时&#xff0c;发现同一后端服务&#xff0c;在单机 500 并发下&#xff0c;HTTP 和 HTTPS 协议压测 RT 差距非常大。同时观测后端服务各监控指标水位都很低&#xff0c;因此怀疑性能瓶颈在 JMeter 施压客户端。二、问题分析切入点&#xff1a;垃…