如何解决Vue中给data中的对象属性添加一个新的属性时响应式不生效的问题?

2024-09-04 14:36

本文主要是介绍如何解决Vue中给data中的对象属性添加一个新的属性时响应式不生效的问题?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

vue2的响应式原理使用的是对象代理去实现的,对象代理中有一个get和set方法,当我们访问对象的时候就会触发get方法,当我们对对象中的值进行修改时会触发set方法。但是当我们给对象添加一个新的属性时对象代理是检测不到的,所以就会出现直接给对象添加属性响应式不生效的问题。

在Vue中,给data中的对象添加一个新属性时,Vue默认不会检测到这个属性的添加,因此,不会触发视图的更新。为了解决这个问题,也就是说怎么才能添加响应式的属性呢?Vue提供了几种方法来添加响应式属性:

1、在vue中可以使用 this.$set(对象名,'属性名',属性值) 的方法去给对象添加属性,或者使用Vue.set(对象名,'属性名',属性值) 的方法进行添加,添加之后的属性就带有响应式了。

示例参看:vue给对象添加属性没有响应式的问题及解决_vue.js_脚本之家

- 使用Vue.set()方法:

Vue.set(vm.someObject, 'newProp', 'value');

通过Vue.set向响应式对象中添加一个property,并确保这个新 property同样是响应式的,且触发视图更新。

- 使用对象的$set()方法(实例方法):

 this.$set(this.someObject, 'newProp', 'value');

番外:Vue.set 方法接收三个参数:

  1. {Object | Array}  target: 响应式对象

  2. {string | number} key: 要设置的属性名  ——propertyName / index

  3. {any} value: 属性值

Vue.set( target, propertyName/index, value )

关于Vue.set源码(省略了很多与本节不相关的代码)

源码位置:src\core\observer\index.js

注:Vue2.6.12版本的源码可参看:https://www.jb51.net/article/269625.htm 

function set (target: Array<any> | Object, key: any, val: any): any {...defineReactive(ob.value, key, val)ob.dep.notify()return val
}

这里无非再次调用defineReactive方法,实现新增属性的响应式

关于defineReactive方法,内部还是通过Object.defineProperty实现属性拦截

大致代码如下:

function defineReactive(obj, key, val) {Object.defineProperty(obj, key, {get() {console.log(`get ${key}:${val}`);return val},set(newVal) {if (newVal !== val) {console.log(`set ${key}:${newVal}`);val = newVal}}})
}

参考:Vue.set()方法的使用,以及对其进行深入解析

2、使用Object.assign()展开运算符来给对象添加属性,并确保赋值是在Vue的响应式系统的作用范围内:

示例参看:vue给对象添加属性没有响应式的问题及解决_vue.js_脚本之家

直接使用Object.assign()添加到对象的新属性不会触发更新,应创建一个新的对象,合并原对象和混入对象的属性。

// 使用Object.assign
this.someObject = Object.assign({}, this.someObject, { newProp: 'value' });

3、使用展开运算符:'...' 来给对象添加新属性

// 使用展开运算符
this.someObject = { ...this.someObject, newProp: 'value' };

4、使用this.$forceUpdata()函数使得vue强制更新视图和数据(不推荐使用)。

调用强制更新方法this.$forceUpdate()会更新视图和数据,触发updated生命周期。

如果你发现你自己需要在Vue中做一次强制更新,99.9% 的情况,是你在某个地方做错了事。$forceUpdate()方法迫使Vue实例重新渲染。

PS:仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件。

示例参看:vue给对象添加属性没有响应式的问题及解决_vue.js_脚本之家

小结

  • 如果为对象添加少量的新属性,可以直接采用Vue.set()
  • 如果需要为新对象添加大量的新属性,则通过Object.assign()展开运算符:'...' 创建新对象
  • 如果你实在不知道怎么操作时,可采取$forceUpdate()进行强制刷新 (不建议)

PS:vue3是用过proxy实现数据响应式的,直接动态添加新属性仍可以实现数据响应式

  • 可以直接采用Vue.set()
  • 如果需要为新对象添加大量的新属性,则通过Object.assign()展开运算符:'...' 创建新对象
  • 如果你实在不知道怎么操作时,可采取$forceUpdate()进行强制刷新 (不建议)

因为vue不能检测到对象属性的添加或者删除,只有在data对象上存在的属性是响应式的,所以要使用Vue.set()方法将响应式属性添加到对象上。同样的道理,(Vue 2.6+)使用Vue.delete()vm.$delete()方法来删除属性,同时Vue也能够检测到属性的删除。

综上所述,以上方法可以确保在Vue中给对象添加或删除新属性时,视图能够正确更新。

参考资料

「Vue面试题」动态给vue的data添加一个新的属性时会发生什么?如何去解决?-CSDN博客

使用Vue.$set()或者Object.assign()修改对象新增响应式属性的方法_vue.js_脚本之家

vue给对象添加属性没有响应式的问题及解决_vue.js_脚本之家

动态给vue的data添加⼀个新的属性时会发⽣什么? 怎样解决? - 简书

Vue 中给 data 中的对象属性添加一个新的属性时会发生什么?如何解决?-CSDN博客

这篇关于如何解决Vue中给data中的对象属性添加一个新的属性时响应式不生效的问题?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1136244

相关文章

解决IDEA报错:编码GBK的不可映射字符问题

《解决IDEA报错:编码GBK的不可映射字符问题》:本文主要介绍解决IDEA报错:编码GBK的不可映射字符问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录IDEA报错:编码GBK的不可映射字符终端软件问题描述原因分析解决方案方法1:将命令改为方法2:右下jav

MyBatis模糊查询报错:ParserException: not supported.pos 问题解决

《MyBatis模糊查询报错:ParserException:notsupported.pos问题解决》本文主要介绍了MyBatis模糊查询报错:ParserException:notsuppo... 目录问题描述问题根源错误SQL解析逻辑深层原因分析三种解决方案方案一:使用CONCAT函数(推荐)方案二:

Redis 热 key 和大 key 问题小结

《Redis热key和大key问题小结》:本文主要介绍Redis热key和大key问题小结,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录一、什么是 Redis 热 key?热 key(Hot Key)定义: 热 key 常见表现:热 key 的风险:二、

IntelliJ IDEA 中配置 Spring MVC 环境的详细步骤及问题解决

《IntelliJIDEA中配置SpringMVC环境的详细步骤及问题解决》:本文主要介绍IntelliJIDEA中配置SpringMVC环境的详细步骤及问题解决,本文分步骤结合实例给大... 目录步骤 1:创建 Maven Web 项目步骤 2:添加 Spring MVC 依赖1、保存后执行2、将新的依赖

Spring 中的循环引用问题解决方法

《Spring中的循环引用问题解决方法》:本文主要介绍Spring中的循环引用问题解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录什么是循环引用?循环依赖三级缓存解决循环依赖二级缓存三级缓存本章来聊聊Spring 中的循环引用问题该如何解决。这里聊

Spring Boot中JSON数值溢出问题从报错到优雅解决办法

《SpringBoot中JSON数值溢出问题从报错到优雅解决办法》:本文主要介绍SpringBoot中JSON数值溢出问题从报错到优雅的解决办法,通过修改字段类型为Long、添加全局异常处理和... 目录一、问题背景:为什么我的接口突然报错了?二、为什么会发生这个错误?1. Java 数据类型的“容量”限制

Java对象转换的实现方式汇总

《Java对象转换的实现方式汇总》:本文主要介绍Java对象转换的多种实现方式,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Java对象转换的多种实现方式1. 手动映射(Manual Mapping)2. Builder模式3. 工具类辅助映

关于MongoDB图片URL存储异常问题以及解决

《关于MongoDB图片URL存储异常问题以及解决》:本文主要介绍关于MongoDB图片URL存储异常问题以及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录MongoDB图片URL存储异常问题项目场景问题描述原因分析解决方案预防措施js总结MongoDB图

SpringBoot项目中报错The field screenShot exceeds its maximum permitted size of 1048576 bytes.的问题及解决

《SpringBoot项目中报错ThefieldscreenShotexceedsitsmaximumpermittedsizeof1048576bytes.的问题及解决》这篇文章... 目录项目场景问题描述原因分析解决方案总结项目场景javascript提示:项目相关背景:项目场景:基于Spring

解决Maven项目idea找不到本地仓库jar包问题以及使用mvn install:install-file

《解决Maven项目idea找不到本地仓库jar包问题以及使用mvninstall:install-file》:本文主要介绍解决Maven项目idea找不到本地仓库jar包问题以及使用mvnin... 目录Maven项目idea找不到本地仓库jar包以及使用mvn install:install-file基