Vue3-03-Vue2 响应式 VS Vue3 响应式

news2024/11/25 12:50:22

本文来讲解从 Vue2 到 Vue3 响应式底层的一些改变。

前言

Vue 2.x 为什么不监听数组下标索引值的变化?

参考了很多博主的推文,自己也尝试了一下,Object.defineProperty 是可以做到监听数组的索引值的变化的,来做 getter 和 setter。

但 Vue2.x 为什么没有这么做呢?官方回答是因为性能的问题,所以不监听数组索引值的变化。

一、Vue2 响应式

1. 对象响应性

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

// vm.a 是响应式的
vm.a = 1;

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

为什么会出现这种情况?vm 是一个 Vue 的实例,它带有了 data 对象中的所有的属性,如果我们访问 vm.a,代表我们访问的是 data 数据对象中的 a 属性,

数据对象中的属性都会被转化为 getter 和 setter,vm.a = 2 会触发对应的 setter。vm.b = 2 就是在 vm 对象上添加了一个属性,所以它不会有响应性。

这里就是 Vue2 对对象处理比较薄弱的一块,我们没办法对对象新增的属性进行实时的响应。

2. 数组响应性

var vm = new Vue({
  data: {
    items: ['a', 'b', 'c']
  }
});

vm.items[1] = 'x'; // 不是响应性的

vm.items[1].length = 2; // 不是响应性的

由于 JavaScript 的限制,Vue 不能检测数组和对象的变化。尽管如此,我们还是有办法来回避这些限制并保证它们的响应性。

这里来介绍一个术语:代理原型。

假设我们有一个数组,想要监听这个数组元素的变化,我们首先要找到能够改变数组成员的方法,比如 push、pop 等方法,这些方法都能够改变数组结构。这些方法都是定义在 Array 这个数组的原型对象上,Array 是 JS 内置的一个构造函数。Array 对象的这些方法的代码我们没法去修改,所以这时我们就要想一个办法,我们能不能在要监听的数组和 Array 原型对象间嫁接一层,这个嫁接的一层就是我们所说的代理原型对象(即上图中粉色框)。

原本我们使用 push 方法时,指向的是数组原型对象上的 push 方法。现在我们做了一层嫁接,被监听数组的 __proto__ 指向的是代理原型对象,在代理原型对象中扩展了能改变数组数据结构的方法。在代理原型对象的方法中,需要做2件事。第一件事就是方法的原有行为不变,第二件事为做一些拦截操作,将改变数组结构的操作加入到响应式机制中,去通知触碰了这个数组的所有观察者数组已发生变化。

回到前言中的问题,Vue 2.x 为什么不监听数组下标索引值的变化?原因就是在于 Vue2 的数组响应式是通过代理原型对象实现了,只有调用数组原型对象上的方法改变数组元素时才可以监听到变化。当然也可以为数组的每个元素设置 getter 和 setter,但这样会增加很多不必要的性能损耗。

因此,Vue 提供了一个方法 Vue.set,使用这个方法改变数组和对象的元素可以响应性的被监听到。

二、Vue3 响应式

在 Vue3 中,使用 Proxy 来实现响应性。

Vue3 使用了 Proxy 可以解决 Vue2 中两个不能直接通过语法来解决的问题:

(1) 对新增的响应式对象属性的监听。

(2) 通过数组下标修改数组元素的响应性。

1. Proxy

Proxy 可以理解成,在目标对象之前架设一层拦截,外界对该对象的访问,都必须先通过这层拦截。因此提供了一种机制,可以对外界的访问进行过滤和改写。

2. Vue3 响应式

再来看上篇文章的示例:

const data: DataProps = reactive({
  count: 0,
  double: computed(() => data.count * 2),
  increase: () => {
    data.count++;
  },
});

修改示例代码:

const data: DataProps = reactive({
  count: 0,
  double: computed(() => data.count * 2),
  nums: [1, 2, 3, 4, 5],
  increase: () => {
    data.count++;
    for (let i = 0; i < data.nums.length; i++) {
      data.nums[i]++;
    }
  },
});

在 data 中新增一个数组 nums,元素为 1、2、3、4、5。修改方法 increase,对数组中的所有元素进行自增。

修改模板部分,添加一个 ul 列表,展示 nums 中的元素值。

<ul>
  <li v-for="(item, index) in nums" :key="index"><h2>{{ item }}</h2></li>
</ul>

如果使用 Vue2,显然 increase 方法是不会触发 li 元素值的变化。但在 Vue3 中,是可以响应式修改的。

进入预览页面,可以看到展示出了 nums 的元素:

 点击 button 按钮,列表元素响应式的进行自增:

3. Vue3 数组响应式的简单实现

简单实现代码如下:

var source = [0, 1, 2];

var wrapped = new Proxy(source, {
  get(target, p, receiver) {
    console.log('我侦测到你想对数组下标' + p + '进行访问');
    return Reflect.get(target, p, receiver);
  },
  set(target, p, value, receiver) {
    console.log('我侦测到你想对数组下标' + p + '进行赋值');
    return Reflect.set(target, p, receiver);
  }
});

wrapped[0];
wrapped[2] = 5;

粘贴到浏览器控制台运行,运行结果如下:

可以看到,使用 Proxy 成功监测到了数组下标元素的变化。

三、总结

1. Object.defineProperty 是对对象属性的劫持;Proxy 是对整个对象的劫持。

2. Object.defineProperty 需要手动绑定响应式对象新增属性的响应性;Proxy 能侦测对象新增属性并实时响应。

3. Object.defineProperty 无法侦测数组元素的变化,需要手动设置代理原型;Proxy 能监听数组。

4. Object.defineProperty 启动就递归,不管对象嵌套多深,都把对象上的 property 转化为响应式的;Proxy 只在 getter 时才进行对象下一层属性的劫持。

5. Object.defineProperty 无兼容性问题;Proxy 有兼容性问题(IE)。

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

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

相关文章

基于Yolov8的道路破损检测系统

目录 1.Yolov8介绍 2.数据集介绍 2.1数据集划分 2.2 通过voc_label.py得到适合yolov8训练需要的 2.3生成内容如下 3.训练结果分析 4. 道路破损检测系统设计 4.1 PySide6介绍 4.2 安装PySide6 4.3 道路破损检测系统设计 1.Yolov8介绍 Ultralytics YOLOv8是Ultralytics公司…

Sui x KuCoin Labs夏季黑客松|本周Workshop预告

由Sui和KuCoin Labs联合主办的夏季黑客松正如火如荼的报名中。了解黑客松详情&#xff1a;Sui与KuCoin Labs联合推出夏季黑客松&#xff0c;奖池高达28.5万美金&#xff01; &#x1f449; 黑客松官方网站&#xff1a;Sui x KuCoin Labs Summer Hackathon | Sui x KuCoin Labs…

1.2 几种常用的数制

学习目标&#xff1a; 学习几种常用的数制可以通过以下步骤进行&#xff1a; 1. 确定目标数制&#xff1a;常用的数制包括十进制、二进制、八进制和十六进制。首先&#xff0c;确定你想要学习的数制是哪一种。 2. 理解基本概念&#xff1a;了解每种数制的基本概念是非常重要…

基于云计算的java云HIS系统源码

一、一个好的HIS系统&#xff0c;要具有开放性&#xff0c;便于扩展升级&#xff0c;增加新的功能模块&#xff0c;支撑好医院的业务的拓展&#xff0c;而且可以反过来给医院赋能&#xff0c;最终向更多的患者提供更好的服务。 二、本套基于云计算的云医疗信息系统&#xff08…

【软件环境安装部署】华为云服务器下 Docker 安装 Nacos最新版并配置数据库(避雷版 最详细版 解决 Docker 容器启动 网页打不开等问题)

文章目录 拉取nacos创建挂载目录[mysql新建nacos的数据库 nacos-config&#xff0c;并执行脚本 sql脚本地址如下](https://github.com/alibaba/nacos/blob/master/config/src/main/resources/META-INF/nacos-db.sql)在/data/nacos/init.d文件夹中增加配置文件custom.properties…

SpringBoot项目实现登录验证码校验功能(可以学习,可以作为工具)

此项目只作为验证码存取演示&#xff0c;对于检验等各方面大家进行扩展就行&#xff0c;已经实现了验证码缓存&#xff0c;大家要想进行校验&#xff0c;只需要添加校验逻辑代码即可&#xff01;为了方便演示&#xff0c;直接使用了html界面进行操作&#xff0c;大家可以根据需…

【Charles】-苹果手机 IOS15.4 抓HTTPS包

写在前面 本文以Windows IOS Charles为例&#xff0c;简单说明抓包的原理&#xff0c;配置步骤以及遇到的坑。 目录 写在前面一、场景描述二、具体步骤1.环境说明2.下载Charles安装3.Charles开启代理4.手机端设置代理4.1Windows端操作4.2手机端操作 5.配置SSL5.1Charles安装S…

Html 表格标签和表单标签

表格标签 标签描述&#xff1a; <!DOCTYPE html> <html> <head><meta charset"UTF-8"><title>文档的标题</title> </head><body> <!--标识边框的宽度--> <table border"1"><thead><…

DataOps是现代数据堆栈的未来吗?

DevOps 席卷软件工程世界之前&#xff0c;一旦应用程序启动并运行&#xff0c;开发人员就会一头雾水。 工程师不是第一个知道何时发生中断&#xff0c;而是只会发现客户或利益相关者何时抱怨“网站滞后”或 503 页面过多。 不幸的是&#xff0c;这导致了同样的错误反复出现&a…

金九银十Java面试八股文大全1200道面试题附答案详解(2023版)

Java 面试八股文有必要背吗&#xff1f; 我的回答是&#xff1a;很有必要。你可以讨厌这种模式&#xff0c;但你一定要去背&#xff0c;因为不背你就进不了大厂。现如今&#xff0c;Java 面试的本质就是八股文&#xff0c;把八股文面试题背好&#xff0c;面试才有可能表现好。…

php怎么在线预览word文件?php预览.doc、.docx、.wps文件

php预览Word PHP要实现在线Word预览只需要3步 第一步&#xff1a; 准备一个文件地址&#xff0c;如下&#xff1a; http://usdoc.cn/vw/文件模板.docx 第二步 预览前置地址&#xff1a; http://vw.usdoc.cn/?src 第三步 开始预览 http://vw.usdoc.cn/?srchttp://usdoc.cn/vw/…

windows10家庭版禁用Device/Credential Guard解决方案

文章目录 背景&#xff08;禁用的原因&#xff09;解决的方式方式一&#xff1a;通过Windows本身的功能设置禁用 ( 非家庭版的使用)1. 禁用Device Guard或Credential Guard&#xff1a;2. 关闭Hyper-V选项3. 重启电脑 方式二&#xff1a;通过命令关闭Hyper-V ( Windows 10家庭版…

Liunx 安装 Miniconda与Python环境

在国内从官网上下载安装包会比较慢&#xff0c;下载最新版容易&#xff0c;过往版本不易寻找。生信软件一般建议使用过往的稳定版本&#xff0c;尤其是公司集群的系统版本低&#xff0c;很容易版本不匹配。推荐从清华大学的源下载。 下载 ## anaconda的官网地址 https://www…

网络层:IP数据报的发送和转发过程

网络层&#xff1a;IP数据报的发送和转发过程 笔记来源&#xff1a; 湖科大教书匠&#xff1a;IP数据报的发送和转发过程 声明&#xff1a;该学习笔记来自湖科大教书匠&#xff0c;笔记仅做学习参考 IP数据报的发送和转发过程包含两个部分&#xff1a; 主机发送IP数据报 路由器…

Maven配置文件settings.xml 和 jar包下载失败处理

1.配置国内的Maven源1.1 mirrors代码 2.重新下载jar包3.其他问题 1.配置国内的Maven源 1.先打开自己的Idea检测Maven是否配置正确。 Idea的设置分两种&#xff1a;一是配置当前项目&#xff1b;二是配置新项目&#xff0c;所以下述所有配置操作我们需要操作两次 2.检查settings…

PMP项目管理证书是什么?有什么用?

什么是PMP证书&#xff1f; PMP全称是Project Management Professional&#xff0c;中文全称叫项目管理专业人士资格认证&#xff0c;是由美国项目管理协会(PMI)发起&#xff0c;严格评估项目管理人员知识技能是否具有高品质的资格认证考试&#xff0c;目的是为了给项目管理人…

3D格式转换工具HOOPS Exchange​助力Zuken打造电子设计自动化产品

行业&#xff1a;电子制造 挑战&#xff1a;对制造商来说&#xff0c;电子设计变得越来越复杂 - 电气和机械设计的融合需要将二维和三维数据结合起来 - 需要提供对多种不同CAD格式的支持 解决方案&#xff1a;HOOPS Exchange是用于快速、准确的CAD数据转换的领先SDK&#xff…

vscode右键点击,松开后自动触发鼠标所在位置的按钮(误触发双击效果)

例如如下&#xff0c;右键展开菜单&#xff0c;松手会自动触发转到声明功能 解决方案&#xff1a; 1、安装easystroke sudo apt-get install easystroke 2、打开easystroke&#xff0c;选择preferences tab 3、点击Gesture Button&#xff0c;在出现的框中右键单击一次 4、点…

基于python的数据集扩充增强

前言 数据增强技术在深度学习中得到了广泛的应用&#xff0c;它能够有效地扩充训练数据集的大小&#xff0c;提高模型的泛化能力&#xff0c;同时也能够有效地防止过拟合现象的发生。在本篇中&#xff0c;将讲解一种基于 Python 和 OpenCV 库实现的数据增强方法&#xff0c;并提…

Notes/Domino 14新变化

大家好&#xff0c;才是真的好。 一周没见&#xff0c;有没有分外想念&#xff1f; 这周马上要发布HCL Notes/Domino 14 Drop1版本&#xff0c;许多人摩拳擦掌&#xff0c;跃跃欲试。今天我们就不说功能&#xff0c;而从底层来说&#xff0c;这回14版本带来的变化真的很大&am…