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

vue.js 更新数据时,出现数据更新,界面没有更新的情况【普通对象,不包含数组】

问题出现

代码如下:

<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>列表</title><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><style>body {padding: 20px;}</style></head><body><div id="app"><div><button @click="updateData()">更新张伟信息</button></div><div style="margin-top: 20px;"><div v-for="(item,index) in persons" :key="item.id"><span>{{item.name}}</span><span>-</span><span>{{item.age}}</span><span>-</span><span>{{item.gender}}</span></div></div></div></body><script>var vm = new Vue({el: '#app',data() {return {persons: [{id: 1,name: '张伟',age: 32,gender: '男'},{id: 2,name: '王芳',age: 28,gender: '女'},{id: 3,name: '李娜',age: 25,gender: '女'},{id: 4,name: '赵强',age: 40,gender: '男'},{id: 5,name: '刘洋',age: 30,gender: '男'},{id: 6,name: '陈静',age: 27,gender: '女'},{id: 7,name: '杨磊',age: 35,gender: '男'},{id: 8,name: '黄丽',age: 26,gender: '女'},{id: 9,name: '吴杰',age: 38,gender: '男'},{id: 10,name: '周敏',age: 29,gender: '女'}],}},mounted() {},methods:{updateData(){this.persons[0]={id: 1,name: '张伟111',age: 32,gender: '男'}console.log(this.persons)},},})</script>
</html>

按照希望的的情况,点击按钮的时候,第一行数据的name 应该从张伟 变成 张伟111 。但是实际情况?
在这里插入图片描述

数据更新的原理

Vue(尤其是 Vue 2 和 Vue 3)对数据变化的监测机制是其响应式系统的核心,理解这一机制有助于更高效地开发和调试 Vue 应用。下面将分别解释 Vue 2 和 Vue 3 的监测原理。

Vue 2 的数据监测原理(基于 Object.defineProperty)

核心原理:Object.defineProperty

Vue 2 通过递归地遍历对象的属性,并使用 Object.defineProperty 将其转化为“getter”和“setter”,从而拦截对数据的读取和修改。

Object.defineProperty(obj, 'key', {get() {// 收集依赖return value;},set(newVal) {// 触发更新value = newVal;}
});

Observer 模式

Vue 2 内部构建了一个 Observer 类,对每个对象进行监听。每当数据被读取时,收集当前组件(Watcher),当数据被修改时通知这些 Watcher 重新执行。

缺点与局限性

  • 新增属性无响应:必须使用 Vue.set 才能让新属性响应式。
  • 数组监听有限:只能监听数组的变异方法(如 push/pop/splice),无法拦截通过索引直接设置值(如 arr[0] = 1)。

Vue 3 的数据监测原理(基于 Proxy)

核心原理:Proxy

Vue 3 放弃了 Object.defineProperty,转而使用现代浏览器支持的 Proxy。它可以直接监听整个对象的操作,包括属性读取、设置、删除等,甚至能监听数组索引和新增属性。

const proxy = new Proxy(target, {get(target, key, receiver) {// 依赖收集return Reflect.get(target, key, receiver);},set(target, key, value, receiver) {// 派发更新return Reflect.set(target, key, value, receiver);}
});

优势

  • 支持 数组索引 和 新增属性。
  • 不再需要递归地遍历所有属性(延迟代理)。
  • 可以更好地检测对象何时被访问或修改。

响应式系统的两个重要角色

Dep(依赖收集)

每个响应式属性都有一个依赖管理器(Dep),用来记录哪些 Watcher(组件或计算属性)使用了这个数据。

Watcher(依赖执行者)

当组件使用响应式数据时,会生成对应的 Watcher,并自动订阅这个数据的变化;当数据改变时,这些 Watcher 会被通知,从而触发组件更新或重新计算。

总结对比

特性 Vue 2 (defineProperty)Vue 3 (Proxy)
新增属性响应式❌ 需手动 Vue.set✅ 自动监听
数组索引变更❌ 无法监听✅ 支持
性能递归劣化性能延迟代理,性能优
API 支持度老浏览器兼容好需现代浏览器

如果你想深入调试 Vue 的响应式系统,可以尝试查看源码中的以下文件:

  • Vue 2:src/core/observer/index.js
  • Vue 3:@vue/reactivity 包下的 reactive.ts

修改之后的代码

<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>列表</title><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><style>body {padding: 20px;}</style></head><body><div id="app"><div><button @click="updateData()">更新张伟信息</button></div><div style="margin-top: 20px;"><div v-for="(item,index) in persons" :key="item.id"><span>{{item.name}}</span><span>-</span><span>{{item.age}}</span><span>-</span><span>{{item.gender}}</span></div></div></div></body><script>var vm = new Vue({el: '#app',data() {return {persons: [{id: 1,name: '张伟',age: 32,gender: '男'},{id: 2,name: '王芳',age: 28,gender: '女'},{id: 3,name: '李娜',age: 25,gender: '女'},{id: 4,name: '赵强',age: 40,gender: '男'},{id: 5,name: '刘洋',age: 30,gender: '男'}],}},mounted() {},methods:{updateData(){this.$set(this.persons, 0, {id: 1,name: '张伟111',age: 32,gender: '男'})},},})</script>
</html>
http://www.xdnf.cn/news/6887.html

相关文章:

  • NBA足球赛事直播源码体育直播M33模板赛事源码
  • B站锁定三倍速(自用)
  • Dubbo:Docker部署Zookeeper、Dubbo Admin的详细教程和SpringBoot整合Dubbo的实战与演练
  • gem5-gpu教程 第十章 关于topology 的Mesh network
  • USB基础知识
  • Selenium测试框架快速搭建
  • 多模态学习( 二 )——Token与Embedding的区别:从文本到向量空间的旅程
  • 手动实现 Transformer 模型
  • QT+EtherCAT 主站协议库—SOEM主站
  • 什么是差分传输?
  • 免费代理IP服务有哪些隐患?如何安全使用?
  • 智力题整理汇总版
  • 高频面试题(含笔试高频算法整理)基本总结回顾61
  • 浅谈前端架构设计与工程化
  • 【降维】t-SNE
  • 腾讯 CodeBuddy 杀入 AI 编程赛道,能否撼动海外工具霸主地位?
  • 力扣-283-移动零
  • 中文分词与数据可视化01
  • 板对板连接器极限测试:振动、温差与盐雾三重挑战下的生存实录
  • 我的世界模组开发——特征(2)
  • 【Linux内核】设备驱动之块设备介绍
  • 连续赋值?多变量初始化?变量初始化?赋值运算符?
  • Kotlin 作用域函数(let、run、with、apply、also)对比
  • OCC笔记:Brep格式
  • 文章记单词 | 第94篇(六级)
  • Java 面向对象进阶:抽象类与接口的舞蹈
  • 基于C语言的歌曲调性检测技术解析
  • TTS:F5-TTS 带有 ConvNeXt V2 的扩散变换器
  • bitmap/hyperloglog/GEO详解与案例实战
  • 永久免费!专为 Apache Doris 打造的可视化数据管理工具 SelectDB Studio V1.1.0 重磅发布!