Vue监视数据的原理和set()的使用

在 Vue 中,Vue.set()(或 this.$set())是用于解决响应式数据更新检测的重要方法,其底层与 Vue 的数据监视原理紧密相关。以下从使用场景和实现原理两方面详细说明:

一、Vue.set () 的使用场景与用法

1. 为什么需要 Vue.set ()?

Vue 的响应式系统通过 Object.defineProperty(Vue 2)或 Proxy(Vue 3)实现数据监听,但存在限制:

  • 无法检测对象新增的属性删除的属性
  • 无法检测数组通过索引修改元素修改数组长度的操作。

此时,直接修改数据不会触发视图更新,需要用 Vue.set() 强制触发响应式更新。

2. 用法
  • 语法
    // 全局方法
    Vue.set(target, propertyName/index, value)// 实例方法(组件内)
    this.$set(target, propertyName/index, value)
    
  • 参数
    • target:需要修改的响应式对象或数组(必须是已被 Vue 响应式系统劫持的对象);
    • propertyName/index:新增 / 修改的属性名(对象)或索引(数组);
    • value:对应的值。
3. 典型场景
  • 给对象新增响应式属性

    data() {return {user: { name: '张三' }}
    },
    methods: {addAge() {// 直接新增属性,视图不会更新this.user.age = 20; // 无效// 使用 $set,视图会更新this.$set(this.user, 'age', 20); // 有效}
    }
    
  • 修改数组的指定元素

    data() {return {list: ['苹果', '香蕉']}
    },
    methods: {updateItem() {// 直接通过索引修改,视图不会更新this.list[1] = '橙子'; // 无效// 使用 $set,视图会更新this.$set(this.list, 1, '橙子'); // 有效}
    }
    

二、Vue 监视数据的原理

Vue 实现数据响应式的核心是对数据进行劫持,并在数据变化时通知依赖更新视图。不同 Vue 版本的实现方式略有差异:

1. Vue 2 的响应式原理(Object.defineProperty)
  • 初始化劫持
    当组件初始化时,Vue 会遍历 data 中的所有属性,通过 Object.defineProperty 为每个属性添加 getter 和 setter

    • getter:当属性被访问时触发,用于收集依赖(记录哪些视图 / 计算属性依赖该数据)。
    • setter:当属性被修改时触发,用于通知依赖更新(触发视图重新渲染)。
  • 局限性

    • 只能劫持初始化时已存在的属性,新增属性默认没有 getter/setter,因此无法被监测。
    • 数组的 length 修改和索引赋值不会触发 setter(Vue 对数组的 7 个方法进行了重写,如 pushsplice 等,这些方法会触发更新,但直接修改索引 / 长度不会)。
2. Vue 3 的响应式原理(Proxy)
  • 初始化劫持
    Vue 3 使用 ES6 的 Proxy 对 data 对象进行代理,生成一个代理对象(Proxy)。Proxy 可以拦截对象的所有操作(包括新增属性、删除属性、索引访问等),从而解决了 Vue 2 的局限性。

  • 优势

    • 能监测新增属性proxy.xxx = value 会被 set 拦截);
    • 能监测删除属性delete proxy.xxx 会被 deleteProperty 拦截);
    • 能监测数组索引修改长度变化(通过 set 拦截)。

三、Vue.set () 的底层实现逻辑

Vue.set() 的核心作用是手动为数据添加响应式能力,并触发更新:

  1. 对于对象

    • 检查目标对象是否为响应式对象(是否有 __ob__ 标识,Vue 内部用于标记响应式对象)。
    • 若属性已存在,则直接修改值并触发 setter
    • 若属性不存在,则通过 Object.defineProperty(Vue 2)或 Proxy 的 set 拦截(Vue 3)为新属性添加响应式,并手动触发依赖更新。
  2. 对于数组

    • 调用数组的 splice 方法(Vue 已重写该方法,会触发更新),通过 splice(index, 1, value) 实现元素修改,从而触发视图更新。

总结

  • Vue.set () 的作用:解决 Vue 响应式系统无法检测 “对象新增属性”“数组索引修改” 等操作的问题,强制为数据添加响应式并触发视图更新。
  • 监视数据的原理
    • Vue 2 基于 Object.defineProperty 劫持属性的 getter/setter,实现依赖收集和更新通知。
    • Vue 3 基于 Proxy 代理整个对象,拦截所有操作,天然支持更多场景的监测。

理解这一机制有助于避免 “数据修改后视图不更新” 的常见问题,也能更深入地掌握 Vue 响应式系统的设计思想。

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

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

相关文章

在 Vue 中,如何在回调函数中正确使用 this?

在 Vue 组件中,this 指向当前组件实例,但在回调函数(如定时器、异步请求、事件监听等)中,this 的指向可能会丢失或改变,导致无法正确访问组件的属性和方法。以下是在回调函数中正确使用 this 的几种常见方式…

第4章唯一ID生成器——4.4 基于数据库的自增主键的趋势递增的唯一ID

基于数据库的自增主键也可以生成趋势递增的唯一 ID,且由于唯一ID不与时间戳关联,所以不会受到时钟回拨问题的影响。 4.4.1 分库分表架构 数据库一般都支持设置自增主键的初始值和自增步长,以MySQL为例,自增主键的自增步长由auto_i…

设计模式:Memento 模式详解

Memento 模式详解Memento(备忘录)模式是一种行为型设计模式,用于在不破坏封装性的前提下,捕获并外部化一个对象的内部状态,以便在之后能够将该对象恢复到原先保存的状态。它广泛应用于需要实现撤销(Undo&am…

数据结构(6)单链表算法题(下)

一、环形链表Ⅰ 1、题目描述 https://leetcode.cn/problems/linked-list-cycle 2、算法分析 思路:快慢指针 根据上图所示的流程,我们可以推测出这样一个结论:若链表带环,快慢指针一定会相遇。 那么,这个猜测是否正…

智能制造,从工厂建模,工艺建模,柔性制造,精益制造,生产管控,库存,质量等多方面讲述智能制造的落地方案。

智能制造,从工厂建模,工艺建模,柔性制造,精益制造,生产管控,库存,质量等多方面讲述智能制造的落地方案。

Qt 分裂布局:QSplitter 使用指南

在 GUI 开发中,高效管理窗口空间是提升用户体验的关键。QSplitter 作为 Qt 的核心布局组件,让动态分割窗口变得简单直观。一、QSplitter 核心功能解析 QSplitter 是 Qt 提供的布局管理器,专用于创建可调节的分割区域: 支持水平/垂…

R语言与作物模型(DSSAT模型)技术应用

R语言在DSSAT模型的气候、土壤、管理措施等数据准备,自动化模拟和结果分析上都发挥着重要的作用。一:DSSAT模型的高级应用 1.作物模型的概念 2.DSSAT模型发展现状 3.DSSAT与R语言的安装 4.DSSAT模型的高级应用案例 5.R语言在作物模型参数优化中的应用 6.…

JavaSE:学习输入输出编写简单的程序

一、打印输出到屏幕 Java提供了三种核心输出方法,适合不同场景: System.out.println() 打印内容后 自动换行 System.out.println("Welcome"); System.out.println("to ISS"); // 输出: // Welcome // to ISSSystem.out…

访问者模式感悟

访问者模式 首先有两个东西: 一个是访问者vistor (每一个访问者类都代表了一类操作) 一个是被访问者entity (model /info/pojo/node等等这些都行)也就是是说是一个实体类 其操作方法被抽离给了其他类。 访问者模式的核心思想就是**“把操作从数据结构中分离出来,每种操作…

从零到部署:基于Go和Docker的全栈短链接服务实战(含源码)

摘要:本文将手把手带你使用Go语言,并遵循依赖倒置、分层架构等最佳实践,构建一个高性能、高可用的全栈短链接生成器。项目采用Echo框架、GORM、Redis、MySQL,并通过Docker和Docker Compose实现一键式容器化部署到阿里云服务器。文…

MyBatis_3

上一篇文章,我们学习了使用XML实现MyBatis进行增、删、查、改等操作,本篇文章,我们将学习#{ }和${ }获取方法参数的区别和使用MyBatisXML实现动态SQL语句。 #{ }和${ }的区别 在之前的文章中我们都是使用#{ }进行赋值,但实际上M…

智能图书馆管理系统开发实战系列(一):项目架构设计与技术选型

项目背景 智能图书馆管理系统(ILMS)是一个现代化的桌面应用程序,采用前后端分离架构,结合了Web技术的灵活性和桌面应用的用户体验。本项目从高保真原型设计开始,经过完整的软件开发生命周期,最终实现为一个…

应急前端“黄金3分钟”设计:极端场景下的操作界面极速搭建技术

摘要**地震突发,应急指挥系统的操作界面却因加载缓慢无法及时调取数据;火灾现场,消防员手持终端的操作步骤繁琐,延误救援时机。在分秒必争的极端场景中,传统前端操作界面为何频频 “掉链子”?怎样才能在 “…

【Android】三种弹窗 Fragment弹窗管理

三三要成为安卓糕手 零:布局转换 在很多工程当中用的都是LinearLayout和relativelayout,这两者都可以转化为Constrainlayout 注:这种用法并不能精确转换,具体还是要根据自己的需求来做布局约束一:snackbar显示弹窗 ((2…

【AI绘画】Stable Diffusion webUI 与 ComfyUI 全解析:安装、模型、插件及功能对比

一、Stable Diffusion 与 UI 工具概述 Stable Diffusion 是当前最主流的开源 AI 绘画模型,通过文本描述生成高质量图像。为降低使用门槛,开发者推出了多种图形界面(UI)工具,其中AUTOMATIC1111 webUI(简称 …

ABP VNext + GraphQL Federation:跨微服务联合 Schema 分层

ABP VNext GraphQL Federation:跨微服务联合 Schema 分层 🚀 在微服务架构下,服务之间往往需要相互通信,而 GraphQL Federation 提供了一个有效的解决方案,帮助我们将多个微服务的 GraphQL API 聚合成一个统一的入口…

小程序组件的生命周期,以及在小程序中进行接口请求的方法设置

微信小程序组件生命周期与接口请求方法详解一、小程序组件生命周期微信小程序组件的生命周期指的是组件在不同阶段自动触发的函数,开发者可以利用这些钩子函数在特定时机执行相应操作。小程序组件的生命周期主要分为两类:组件自身生命周期和组件所在页面…

在线游戏玩家与物品交互处理

玩家与物品接触后的判定if (hit ! null && hit.CompareTag("Item")){Debug.Log("捡东西");var worldItem hit.gameObject.GetComponent<WorldItem>();if (worldItem ! null){var inventory GetComponent<PlayerInventory>();if (inv…

深入解析Java Stream 构建:AbstractPipeline

Java Stream 宏观介绍见&#xff1a;深入解析 Java Stream 设计&#xff1a;从四幕剧看流水线设计与执行机制-CSDN博客 PipelineHelper PipelineHelper 是 Java Stream API 内部一个至关重要的辅助类。正如其名&#xff0c;它是一个“管道助手”。可以把它想象成一个执行上下文…

《林景媚与命运回响》

《林景媚与命运回响》——当数据库开始回响命运&#xff0c;现实是否还能被信任&#xff1f;《林景媚数据库宇宙》系列第九部第一章&#xff1a;命运的涟漪公元 2089 年&#xff0c;数据库神谕的运行已趋于稳定&#xff0c;PostgreSQL Quantum Engine&#xff08;PQE&#xff0…