当前位置: 首页 > news >正文

【Vue】响应式与数据劫持

Vue.js 是一个渐进式的 JavaScript 框架,其中最重要的一个特性就是响应式(Reactivity)。Vue 借助数据劫持(Data Observation)技术实现了对数据的响应式更新,当数据发生变化时,它会自动重新渲染视图,这使得构建复杂的用户界面变得更加容易。

在本文中,我们将介绍 Vue.js 中的响应式原理和数据劫持机制,让你了解 Vue.js 是如何通过监听数据变化来实现视图更新。

 响应式原理

Vue.js 的响应式原理是基于数据驱动的,它的核心是将数据和视图进行关联,并且在数据发生变化时更新视图。Vue.js 通过数据劫持技术实现了响应式原理。

所谓数据劫持,就是通过一些手段来劫持 JavaScript 对象的访问和修改,以便在数据发生变化时能够自动更新视图。

Vue.js 中的响应式原理流程如下:

1. Vue 组件中有一个 data 属性,它是一个对象。


2. Vue 在初始化组件时,会通过 Object.defineProperty() 方法将 data 中的所有属性都转化成 getter 和 setter。


3. 当访问或者修改这些属性时,会触发对应的 getter 和 setter 方法。


4. 在 setter 方法中,Vue 会通知相关的 Watcher(一个观察者对象)去更新视图。


5. 当组件中的 data 发生变化时,会触发对应属性的 setter 方法,然后通知相关的 Watcher 更新视图。

下面我们将详细介绍 Vue.js 中的数据劫持技术。

数据劫持

数据劫持是 Vue.js 实现响应式的核心技术之一,它主要通过 Object.defineProperty() 方法来实现。Object.defineProperty() 方法是 JavaScript 原生提供的 API,它可以用来定义对象上的属性。这个方法有三个参数:

Object.defineProperty(obj, prop, descriptor)

* obj:要定义属性的对象。
* prop:要定义或修改的属性的名称。
* descriptor:要定义或修改的属性的描述符。

descriptor 是一个包含属性的特性的对象,它具有以下几个属性:

* configurable:当且仅当该属性的 configurable 为 true 时,该属性描述符才能够被改变,同时该属性也能够被删除,默认为 false。
* enumerable:当且仅当该属性的 enumerable 为 true 时,该属性才会出现在对象的枚举属性中,默认为 false。
* value:该属性对应的值,默认为 undefined。
* writable:当且仅当该属性的 writable 为 true 时,该属性才能被赋值运算符改变,默认为 false。
* get:表示该属性的 getter 函数,默认为 undefined。
* set:表示该属性的 setter 函数,默认为 undefined。

通过 Object.defineProperty() 方法,可以给对象的属性设置 getter 和 setter。这样一来,我们就可以在属性被访问或者修改时,触发对应的 getter 和 setter 方法,达到数据劫持的目的。

在 Vue.js 中,当初始化组件时,Vue.js 会对组件中所有的 data 属性使用 Object.defineProperty() 方法将其转化为 getter 和 setter。这样一来,当组件中的 data 属性被访问或者修改时,Vue.js 就能够捕获到这些操作,并在内部执行相应的逻辑。这就实现了 Vue.js 中的响应式机制。

下面是一个简单的示例,我们将使用 Object.defineProperty() 方法来实现一个响应式对象:

var obj = {};Object.defineProperty(obj, "name", {get: function() {console.log("访问了属性 name");return this._name;},set: function(value) {console.log("修改了属性 name,新值为:" + value);this._name = value;}
});obj.name = "Vue.js";
console.log(obj.name);

在这个示例中,我们使用 Object.defineProperty() 方法定义了一个对象 obj 的属性 name。在 getter 和 setter 中,我们分别输出了访问和修改属性的操作,并打印出了属性的值。当我们执行 obj.name = "Vue.js" 时,会触发 setter 方法,并输出修改操作的信息。当我们访问 obj.name 时,会触发 getter 方法,并输出访问操作的信息。

响应式实现

在了解了数据劫持的原理之后,我们来看看 Vue.js 是如何实现响应式的。

我们先来看一个简单的示例,下面是一个 Vue 组件的代码:

<div id="app"><p>{{ message }}</p>
</div>
<script>
new Vue({el: "#app",data: {message: "Hello, Vue.js!"}
});
</script>

在这个组件中,我们使用了 Vue.js 的数据绑定语法 {{ message }} 来显示 data 中的 message 属性。在初始化时,Vue.js 会将组件中的 data 属性转化为 getter 和 setter,代码如下:

function defineReactive(obj, key, val) {Object.defineProperty(obj, key, {get: function() {console.log("访问了属性 " + key);return val;},set: function(newVal) {console.log("修改了属性 " + key + ",新值为:" + newVal);val = newVal;}});
}function observe(obj) {if (!obj || typeof obj !== "object") {return;}Object.keys(obj).forEach(function(key) {defineReactive(obj, key, obj[key]);});
}function Vue(options) {this._data = options.data;observe(this._data);
}

在这个代码中,我们定义了三个函数:defineReactive()、observe() 和 Vue()。

* defineReactive():这个函数用来给对象添加 getter 和 setter,实现数据劫持。

* observe():这个函数会递归遍历对象中的所有属性,将其转化为 getter 和 setter。

* Vue():这个函数用来初始化 Vue 组件,其中 options.data 属性就是我们要响应式的数据。

我们在 Vue() 函数中调用了 observe(),将 data 属性转化为 getter 和 setter。在 defineReactive() 函数中,我们调用了 Object.defineProperty() 方法,将 data 中的每个属性都转化为 getter 和 setter。这样一来,当我们访问或者修改组件中的 data 属性时,就会触发相应的 getter 和 setter 方法,打印出访问或者修改属性的信息。

我们来运行一下这个示例,在控制台中可以查看到输出的信息:
访问了属性 message
Hello, Vue.js!
修改了属性 message,新值为:Hello, Vue.js!
访问了属性 message
Hello, Vue.js!

在这个示例中,我们成功地将组件中的 data 属性转化为了响应式的数据。当我们访问或者修改属性时,都会触发对应的 getter 和 setter 方法,并输出相应的信息。

数据更新

数据劫持的目的是为了在数据发生变化时,能够自动更新视图。在 Vue.js 中,当数据发生变化时,会触发相应的 getter 和 setter 方法,然后通知相关的 Watcher 更新视图。

Watcher 是 Vue.js 中核心的观察者对象,它可以监听数据的变化,当数据发生变化时,会触发更新视图的操作。

当一个 Vue 组件被创建时,会创建一个渲染 Watcher,它会监听组件中的模板(template)和 data 数据。当组件中的 data 数据发生变化时,渲染 Watcher 就会重新渲染组件。

当我们在组件中访问 data 数据时,就会触发一次 getter 方法,并将当前的 Watcher 添加到一个全局的栈中。这个栈叫做 Dep(依赖),它会保存当前的 Watcher 实例。

当 data 数据发生变化时,会触发对应的 setter 方法,并通知 Dep 中保存的所有 Watcher 实例进行更新操作。

在更新时,渲染 Watcher 会先将组件的 VNode(虚拟 DOM)重新渲染,然后再将新的 VNode 与旧的 VNode 进行比对,找出需要更新的部分,最后将差异更新到真实的 DOM 上。

总结


Vue.js 的响应式原理是基于数据驱动的,它通过数据劫持技术实现了对数据的响应式更新。当数据发生变化时,会自动重新渲染视图。

Vue.js 的数据劫持技术是通过 Object.defineProperty() 方法来实现的,这个方法可以定义对象上的属性,并给属性设置 getter 和 setter,达到数据劫持的目的。

在 Vue.js 中,当组件中的 data 数据发生变化时,会触发对应的 setter 方法,并通知相关的 Watcher 更新视图。

在更新视图时,Vue.js 会先重新渲染 VNode,然后进行差异比对,更新差异部分到真实的 DOM 上。

相关文章:

【Vue】响应式与数据劫持

Vue.js 是一个渐进式的 JavaScript 框架&#xff0c;其中最重要的一个特性就是响应式&#xff08;Reactivity&#xff09;。Vue 借助数据劫持&#xff08;Data Observation&#xff09;技术实现了对数据的响应式更新&#xff0c;当数据发生变化时&#xff0c;它会自动重新渲染视…...

Modbus RTU转Profinet网关连接PLC与变频器通讯在机床上应用案例

背景&#xff1a;以前在机床加工车间里&#xff0c;工人们忙碌地操作着各种机床设备。为了使整个生产过程更加高效、流畅&#xff0c;进行智能化改造。 方案&#xff1a;在机床上&#xff0c;PLC通过Modbus RTU转Profinet网关连接变频器进行通讯&#xff1a;PLC作为整个生产线…...

Autoware 整体架构

Autoware 整体架构 测试...

【maven】手动指定jar推送

说明 为了推送第三方的jar&#xff0c;有时需要指定对应的jar推送到私有仓库。 示例 mvn deploy:deploy-file --settings /home/xxx/.m2/settings.xml -DgroupIdgroupId的值 -DartifactIdartifactId的值 -Dversionjar包的版本号 -Dpackagingjar -Dfilejar的路径 -Durlhttp:/…...

算法---定长子串中元音的最大数目

题目 给你字符串 s 和整数 k 。 请返回字符串 s 中长度为 k 的单个子字符串中可能包含的最大元音字母数。 英文中的 元音字母 为&#xff08;a, e, i, o, u&#xff09;。 示例 1&#xff1a; 输入&#xff1a;s “abciiidef”, k 3 输出&#xff1a;3 解释&#xff1a;…...

美国汽车零部件巨头 AutoZone 遭遇网络攻击

Security Affairs 网站披露&#xff0c;美国汽车配件零售商巨头 AutoZone 称其成为了 Clop MOVEit 文件传输网络攻击的受害者&#xff0c;导致大量数据泄露。 AutoZone 是美国最大的汽车零配件售后市场经销商之一&#xff0c;在美国、墨西哥、波多黎各、巴西和美属维尔京群岛经…...

WPF面试题入门篇

入门篇[2] 1. 谈谈什么是WPF&#xff1f; WPF&#xff08;Windows Presentation Foundation&#xff09;是微软公司开发的一种用于创建Windows应用程序的用户界面框架。它是.NET Framework的一部分&#xff0c;提供了一种基于XAML&#xff08;可扩展应用程序标记语言&#xf…...

opencv-ORB检测

ORB&#xff08;Oriented FAST and Rotated BRIEF&#xff09;是一种图像特征检测和描述算法&#xff0c;结合了 FAST 关键点检测器和 BRIEF 描述子的优点。ORB 算法具有良好的性能&#xff0c;特别适用于实时应用&#xff0c;如目标追踪、相机定位等。 以下是 ORB 算法的一般…...

please upgrade numpy version to >=1.20

升级 upgrade numpy_升级numpy-CSDN博客 pip install numpy --upgrade 没有pip conda install numpy --upgrade 会报错 conda list numpy来查看numpy版本 似乎这个numpy要看numpy-base这个 似乎没有pip...

关于进制的转化

二进制转十进制&#xff1a; &#x1f530; 方法一&#xff1a;二进制转十进制&#xff0c;用各数的码位与位权的乘积之和&#xff0c;说白了就是用从右到左的每个数去乘以2的幂次方&#xff08;最右边是0&#xff09;&#xff0c;然后就所有的数相加。 补充&#xff1a;位权是…...

JVM 之 字节码指令

目录 一. 前言 二. 指令集 2.1. 支持的数据类型 2.2. 指令分类 三. 指令手册 3.1. 操作数栈 3.2. 运算与转换 3.3. 条件转移 3.4. 类与数组 3.5. 调度与返回加 finally 3.6. 指令手册汇总 3.7. 示例 一. 前言 字节码指令集的特点是数据量短小精干&#xff0c;便于传…...

阿里云跨账号建立局域网

最近有活动&#xff0c;和好友一并薅了下阿里云的羊毛。琢磨着两台机器组一个局域网&#xff0c;于是有了这个需求&#xff0c;把步骤记录一下&#xff1a; 假设两台机器叫A和B&#xff0c;我们开始进行建立和组网 1. 建立ECS 把A机器公共环境装好&#xff0c;然后使用《实例与…...

【OpenSTL】方便好用的时空预测开源库

OpenSTL&#xff1a;方便好用的时空预测开源库 时空预测学习是一种学习范式&#xff0c;它使得模型能够通过在无监督的情况下从给定的过去帧预测未来帧&#xff0c;从而学习空间和时间的模式。尽管近年来取得了显著的进展&#xff0c;但由于不同的设置、复杂的实现和难以复现性…...

【Unity】IBeginDragHandler、IDragHandler 和 IEndDragHandler 介绍

IBeginDragHandler、IDragHandler 和 IEndDragHandler 介绍 IBeginDragHandler、IDragHandler 和 IEndDragHandler 是 Unity 引擎中的三个接口&#xff0c;用于处理 UI 元素的拖放事件。这些接口通常结合使用&#xff0c;构成了 Unity 引擎的拖放事件系统。 IBeginDragHandler…...

杰发科技AC7801——Flash模拟EEP内存分布情况

简介 本文记录了在使用AutoChips芯片Flash模拟EEP过程中的一些理解 核心代码如下 #include <stdlib.h> #include "ac780x_sweeprom.h" #include "ac780x_debugout.h"#define SWEEPROM_SIZE (2048UL) /* Ssoftware eeprom size(Byte) */ #define TE…...

【前端知识】Node——http模块url模块的常用操作

一、创建简易Server const http require(http); const URL require(url);const HTTP_PORT 8088;const server http.createServer((req, res) > {// req&#xff1a;request请求对象&#xff0c;包含请求相关的信息&#xff1b;// res&#xff1a;response响应对象&…...

平衡二叉树 (简单易懂)

目录 一、概念 二、性质 三、插入操作 四、旋转操作 五、删除操作 六、代码实现 七、复杂度 一、概念 平衡二叉树&#xff08;Balanced Binary Tree&#xff09;是一种特殊的二叉搜索树&#xff08;Binary Search Tree&#xff0c;BST&#xff09;&#xff0c;它在插入和…...

Vue.observable 是什么

Observable 翻译过来我们可以理解成可观察的 Vue.js2.6 新增 Vue.observable&#xff0c;让一个对象变成响应式数据。Vue 内部会用它来处理 data 函数返回的对象 。 返回的对象可以直接用于渲染函数和计算属性内&#xff0c;并且会在发生变更时触发相应的更新。也可以作为最小化…...

【五年创作纪念日】

机缘 我成为创作者的过程并不复杂&#xff0c;可以说是一个自然的发展。我是一名软件工程师&#xff0c;日常的工作主要是编程和解决问题。在工作的过程中&#xff0c;我发现有很多时候我需要查找一些特定的技术问题或者寻找一些最佳实践来解决我遇到的问题。在这个过程中&…...

数据库基础入门 — SQL排序与分页

我是南城余&#xff01;阿里云开发者平台专家博士证书获得者&#xff01; 欢迎关注我的博客&#xff01;一同成长&#xff01; 一名从事运维开发的worker&#xff0c;记录分享学习。 专注于AI&#xff0c;运维开发&#xff0c;windows Linux 系统领域的分享&#xff01; 本…...

HTML 语义化

目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案&#xff1a; 语义化标签&#xff1a; <header>&#xff1a;页头<nav>&#xff1a;导航<main>&#xff1a;主要内容<article>&#x…...

Debian系统简介

目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版&#xff…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂

蛋白质结合剂&#xff08;如抗体、抑制肽&#xff09;在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上&#xff0c;高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术&#xff0c;但这类方法普遍面临资源消耗巨大、研发周期冗长…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装&#xff1b;只需暴露 19530&#xff08;gRPC&#xff09;与 9091&#xff08;HTTP/WebUI&#xff09;两个端口&#xff0c;即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

条件运算符

C中的三目运算符&#xff08;也称条件运算符&#xff0c;英文&#xff1a;ternary operator&#xff09;是一种简洁的条件选择语句&#xff0c;语法如下&#xff1a; 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true&#xff0c;则整个表达式的结果为“表达式1”…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互

引擎版本&#xff1a; 3.8.1 语言&#xff1a; JavaScript/TypeScript、C、Java 环境&#xff1a;Window 参考&#xff1a;Java原生反射机制 您好&#xff0c;我是鹤九日&#xff01; 回顾 在上篇文章中&#xff1a;CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

【HTTP三个基础问题】

面试官您好&#xff01;HTTP是超文本传输协议&#xff0c;是互联网上客户端和服务器之间传输超文本数据&#xff08;比如文字、图片、音频、视频等&#xff09;的核心协议&#xff0c;当前互联网应用最广泛的版本是HTTP1.1&#xff0c;它基于经典的C/S模型&#xff0c;也就是客…...

Fabric V2.5 通用溯源系统——增加图片上传与下载功能

fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...

在Ubuntu24上采用Wine打开SourceInsight

1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...

Unity中的transform.up

2025年6月8日&#xff0c;周日下午 在Unity中&#xff0c;transform.up是Transform组件的一个属性&#xff0c;表示游戏对象在世界空间中的“上”方向&#xff08;Y轴正方向&#xff09;&#xff0c;且会随对象旋转动态变化。以下是关键点解析&#xff1a; 基本定义 transfor…...