vue2和vue3响应式原理
Object.DefineProperty
配置对象的主要属性有:
value:20 //添加的属性的value enumerable:true //是否可以被枚举获取到 默认:false writeable:true //value是否可以被修改 默认:false configurable:true //是否可以被删除 默认:false get(){} //当这个属性被获取的时候调用 set(){} //当这个属性被修改的时候调用
Object.defineProperty(对象,要添加得键,{配置对象})
vue2响应式的缺陷
1.使用对象上定义新属性时,Object.defineProperty监听不到。**因为Object.DefineProperty只能对对象的单个属性劫持,如果要对对象进行劫持,需要遍历。
const user = {name: "jack",} var name = user.name;Object.defineProperty(user, "name", {enumerable: true,writeable: true,configurable: true,
get() {return name},set(e) {name = e}})user.age = 20; // 并没有触发setconsole.log(user);delete user.age; //并没有触发setconsole.log(user);
2.Object.defineProperty无法监控到数组下标的变化。
let arr = [1, 2, 3]let obj = {}//把arr作为obj的属性监听Object.defineProperty(obj, 'arr', {get() {console.log('触发了get')return arr},set(newVal) {console.log('触发了set', newVal)arr = newVal}})console.log(obj.arr) //触发了get [1,2,3] obj.arr = [1, 2, 3, 4] //触发了set [1,2,3,4] obj.arr.push(5) //触发了getobj.arr.unshift() //触发了getobj.arr.pop() // //触发了getobj.arr.shift() //触发了get
3 object.defineProperty 只能劫持对象的属性。从而需要对每个对象,每个属性进行遍历,如果,属性值是对象,还需要深度遍历
const data = {name: 'jack',age: 20,children: {name: 'john'}}
function observer(target) {if (target === null || typeof target !== 'object') {return target}for (let key in target) {//target[key]作为valuelet value = target[key]observer(value)//调用自身,监控内部对象,如果不加遍历不到嵌套对象中的数据,无法修改Object.defineProperty(target, key, {get() {console.log('Object.defineProperty触发了get');return value},set(newValue) {console.log('Object.defineProperty触发了set');if (newValue !== value) {value = newValue//updateView()}}})}}observer(data)data.children.name = 'marray'//此时会调用get和set方法修改数据
Vue3中使用的响应式Proxy
在Vue3中则是使用Proxy来进行数据劫持,Proxy不同于Object.defineProperty的是,它是对整个数据对象进行数据劫持,而Object.defineProperty是对数据对象的某个属性进行数据劫持(如果是多层需要循环绑定)。
Proxy 对象用于定义基本操作的自定义行为(如属性查找、赋值、枚举、函数调用等)。IE不兼容。基本格式为:
const p = new Proxy(target, handler) 参数: target: 要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。 handler: 一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为。
handler 对象是一个容纳一批特定属性的占位符对象。它包含有 Proxy 的各个捕获器(trap):
handler.getPrototypeOf() handler.setPrototypeOf() handler.isExtensible() handler.preventExtensions() handler.getOwnPropertyDescriptor() handler.defineProperty() handler.has()//in 操作符的捕捉器。 handler.get(target, property) handler.set(target, property, value) handler.deleteProperty()//delete 操作符的捕捉器。 handler.ownKeys() handler.apply() handler.construct()//new 操作符的捕捉器。
Proxy的应用——监控数组下标变化
let arr=[1,2,3]let handler={get(target, key, receiver) {console.log('get的key为 ===>' + key);return Reflect.get(target, key, receiver);},set(target, key, value, receiver){console.log('set的key为 ===>' + key, value);return Reflect.set(target, key, value, receiver);}}let p=new Proxy(arr,handler);console.log(p[0]);//get的key为 ===>0//1console.log(p.push(4));//get的key为 ===>push//get的key为 ===>length//set的key为 ===>3 4//set的key为 ===>length 4//4console.log(p);//Proxy {0: 1, 1: 2, 2: 3, 3: 4}console.log(p.shift());//get的key为 ===>shift// get的key为 ===>length// get的key为 ===>0// get的key为 ===>1// set的key为 ===>0 2// get的key为 ===>2// set的key为 ===>1 3// get的key为 ===>3// set的key为 ===>2 4// set的key为 ===>length 3// 1console.log(p);//Proxy {0: 2, 1: 3, 2: 4}
//reflect也是es6的语法,再proxy使用中常用到reflect,reflect有14中方法,
//对应proxy是一样的,但是这俩其实没关系,只是搭配着使用,proxy用来拦截,reflect用来操作。
首先我们可以看到Proxy可以监控到数组下标的变化。 在使用push时先将push的值添加到数组中,再更新数组长度,所以才会有两次get和set。 在使用shift时首先要获取到要删除的元素下标,并删除,再更新每个下标的元素,再更新数组长度。
Proxy的应用——监控对象属性的变化
const user = {name: "jack",}let handler={get(target, key, receiver) {console.log('get的key为 ===>' + key);return Reflect.get(target, key, receiver);},set(target, key, value, receiver){console.log('set的key为 ===>' + key, value);return Reflect.set(target, key, value, receiver);}}let p=new Proxy(user,handler);console.log(p.age=10);// set的key为 ===>age 10// 10console.log(p);//Proxy {name: 'jack', age: 10}
Proxy的应用——监控嵌套对象的数据变化
let obj={name: "jack",phone:{main:10086,else:110}};let handler={get:function(obj,prop){console.log('proxy触发了get');const v = Reflect.get(obj,prop);if(v !== null && typeof v === 'object'){return new Proxy(v,handler);//代理内层}else{return v; // 返回obj[prop]}},set(obj,prop,value){console.log('proxy触发了set');return Reflect.set(obj,prop,value);//设置成功返回true}};let p=new Proxy(obj,handler);
console.log(p.name);//会触发get方法//proxy触发了get//jackconsole.log(p.phone.main);//会先触发get方法获取p.b,然后触发返回的新代理对象的.c的set。//proxy触发了get//proxy触发了get//10086
由此我们可以看到如果我们想要获取到内部N层的数据,proxy就会调用N次get。且proxy在实现监控嵌套对象仅需要一个递归即可实现。
总结Proxy和Object.defineProperty的区别
1.Proxy性能优于Object.defineProperty。 Proxy代理的是整个对象Object.defineProperty只代理对象上的某个属性,如果是多层嵌套的数据需要循环递归绑定;
2.对象上定义新属性时,Proxy可以监听到,Object.defineProperty监听不到。
3.数组使用下标获取和修改Object.defineProperty监听不到,Proxy可以监听到。
4.Proxy在ie浏览器存在兼容性问题
相关文章:
vue2和vue3响应式原理
Object.DefineProperty配置对象的主要属性有: value:20 //添加的属性的value enumerable:true //是否可以被枚举获取到 默认:false writeable:true //value是否可以被修改 默认:false configurable:true //是否可以被删除 默认:f…...
【面试八股文】每日一题:谈谈你对线程的理解
每日一题-Java核心-谈谈你对线程的理解【面试八股文】 Java线程是Java程序中的执行单元。一个Java程序可以同时运行多个线程,每个线程可以独立执行不同的任务。线程的执行是并发的,即多个线程可以同时执行。 1. 线程的特点 Java中的线程有如下的特点 轻…...
arm开发板 GDB远程调试方法
1.前言 1.在linux下开发,免不了使用gdb调试,但是linux下开发嵌入式,都是跑在ARM板子上的,网上有很多GDB的基础教程,但是能在ARM开发板用的时候,会有各种问题。 比如:*.cpp: No such file or di…...
Linux命令(71)之unxz
linux命令之unxz 1.unxz介绍 linux命令unxz是用来解压由xz命令压缩的文件。unxz等价于xz -d 2.unxz用法 unxz [-c] filename.xz unxz常用参数 参数说明-c <目录>将压缩文件解压到指定目录 3.实例 3.1.解压zzz.txt.xz文件至当前目录 命令: unxz zzz.tx…...
广告牌安全传感器,实时监测事故隐患尽在掌握
在现代城市中,广告牌作为商业宣传的重要媒介,已然成为城市中一道独特的风景线。然而,随着城市迅速发展,广告牌的安全问题也引起了大众关注。广告招牌一般悬挂于建筑物高处,量大面大。由于设计、材料、施工方法的缺陷&a…...
对比学习损失—InfoNCE理论理解
InfoNoise的理解 InfoNCE loss温度系数 τ \tau τ InfoNCE loss 最近在看对比学习的东西,记录点基础的东西 「对比学习」 属于无监督学习的一种,给一堆数据,没有标签,自己学习出一种特征表示。 InfoNCE 这个损失是来自于论文&am…...
贝锐蒲公英助力电子公交站牌联网远程运维,打造智慧出行新趋势
在现代城市公共交通系统中,我们随处可见电子公交站牌的身影。作为公共交通服务的核心之一,电子公交站牌的稳定运行至关重要,公交站台的实时公交状况、公共广告信息,是市民候车时关注的焦点。 某交通科技公司在承接某市智能电子站牌…...
SpringBoot + Vue 微人事(十)
职位管理前后端接口对接 先把table中的数据展示出来,table里面的数据实际上是positions里面的数据,就是要给positions:[] 赋上值 可以在methods中定义一个initPosition方法 methods:{//定义一个初始化positions的方法initPositions(){//发送一个get请求…...
【Redis】Redis哨兵模式
【Redis】Redis哨兵模式 Redis主从模式当主服务器宕机后,需要手动把一台从服务器切换为主服务器,需要人工干预费事费力,为了解决这个问题出现了哨兵模式。 哨兵模式是是一个管理多个 Redis 实例的工具,它可以实现对 Redis 的监控…...
系统架构师---软件重用、基于架构的软件设计、软件模型
目录 软件重用 构件技术 基于架构的软件设计 ABSD方法与生命周期 抽象功能需求 用例 抽象的质量和业务需求 架构选项 质量场景 约束 基于架构的软件开发模型 架构需求 需求获取 标识构件 需求评审 架构设计 架构文档 架构复审 架构实现 架构演化 前言&…...
【Web开发指南】MyEclipse XML编辑器的高级功能简介
MyEclipse v2023.1.2离线版下载 1. 在MyEclipse中编辑XML 本文档介绍MyEclipse XML编辑器中的一些可用的函数,MyEclipse XML编辑器包括高级XML编辑,例如: 语法高亮显示标签和属性内容辅助实时验证(当您输入时)文档内容的源(Sou…...
设计模式-观察者模式(观察者模式的需求衍变过程详解,关于监听的理解)
目录 前言概念你有过这样的问题吗? 详细介绍原理:应用场景: 实现方式:类图代码 问题回答监听,为什么叫监听,具体代码是哪观察者模式的需求衍变过程观察者是为什么是行为型 总结: 前言 在软件设计…...
vue+electron中实现文件下载打开wps预览
下载事件 win.webContents.downloadURL(url) 触发session的will-download事件 win.webContents.session.on(will-download, (event, downloadItem, webContents) > {// 设置文件保存路径// 如果用户没有设置保存路径,Electron将使用默认方式来确定保存路径&am…...
第4章 性能分析中的术语和指标
Linux perf和Intel VTune Profiler工具。 4.1 退休指令与执行指令 考虑到投机执行,CPU执行的指令要不退休指令多。Linux perf使用perf stat -e instruction ./a.exe即可获得退休指令的数量。 4.2 CPU利用率 CPU利用率表示在一段时间内的繁忙程度,用时…...
数字化转型能带来哪些价值?_光点科技
随着科技的迅猛发展,数字化转型已成为企业和组织的一项重要战略。它不仅改变了商业模式和运营方式,还为各行各业带来了诸多新的机遇和价值。在这篇文章中,我们将探讨数字化转型所能带来的价值。 数字化转型能够显著提升效率和生产力。通过引入…...
适用于Android™的Windows子系统Windows Subsystem fo r Android™Win11安装指南
文章目录 一、需求二、Windows Subsystem for Android™Win11简介三、安装教程1.查看BIOS是否开启虚拟化2.安装Hyper-V、虚拟机平台3.启动虚拟机管理程序(可选)4.安装适用于Android™的Windows子系统5.相关设置 一、需求 需要在电脑上进行网课APP(无客户端只有App&…...
hive高频使用的拼接函数及“避坑”
hive高频使用的拼接函数及“避坑” 说到拼接函数应用场景和使用频次还是非常高,比如一个员工在公司充当多个角色,我们在底层存数的时候往往是多行,但是应用的时候我们通常会只需要一行,角色字段进行拼接,这样join其他…...
windows ipv4 多ip地址设置,默认网关跃点和自动跃点是什么意思?(跃点数)
文章目录 Windows中的IPv4多IP地址设置以及默认网关跃点和自动跃点的含义引言IPv4和IPv6:简介多IP地址设置:Windows环境中的实现默认网关跃点:概念和作用自动跃点:何时使用?关于“跃点数”如何确定应该设置多少跃点数&…...
java_免费文本翻译API_小牛翻译
目录 前言 开始集成API 纯文本翻译接口 双语对照翻译接口 指定术语翻译接口 总结 前言 网络上对百度,有道等的文本翻译API集成的文章比较多,所以集成的第一篇选择了小牛翻译的文本翻译API。 小牛翻译文本翻译API,支持388个语种࿰…...
flink消费kafka数据,按照指定时间开始消费
kafka中根据时间戳开始消费数据 import org.apache.flink.api.java.utils.ParameterTool; import org.apache.flink.connector.kafka.source.enumerator.initializer.OffsetsInitializer; import org.apache.flink.kafka.shaded.org.apache.kafka.clients.consumer.OffsetRese…...
树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...
【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验
Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...
AxureRP-Pro-Beta-Setup_114413.exe (6.0.0.2887)
Name:3ddown Serial:FiCGEezgdGoYILo8U/2MFyCWj0jZoJc/sziRRj2/ENvtEq7w1RH97k5MWctqVHA 注册用户名:Axure 序列号:8t3Yk/zu4cX601/seX6wBZgYRVj/lkC2PICCdO4sFKCCLx8mcCnccoylVb40lP...
从实验室到产业:IndexTTS 在六大核心场景的落地实践
一、内容创作:重构数字内容生产范式 在短视频创作领域,IndexTTS 的语音克隆技术彻底改变了配音流程。B 站 UP 主通过 5 秒参考音频即可克隆出郭老师音色,生成的 “各位吴彦祖们大家好” 语音相似度达 97%,单条视频播放量突破百万…...
【笔记】AI Agent 项目 SUNA 部署 之 Docker 构建记录
#工作记录 构建过程记录 Microsoft Windows [Version 10.0.27871.1000] (c) Microsoft Corporation. All rights reserved.(suna-py3.12) F:\PythonProjects\suna>python setup.py --admin███████╗██╗ ██╗███╗ ██╗ █████╗ ██╔════╝…...
