vue3 - 使用reactive定义响应式数据进行赋值时,视图没有改变,值已经改变的解决方案

2023-09-15 15:20:27

问题:

        在Vue 3.0 中我们使用 reactive() 定义的响应式数据的时候,当是一个数组或对象时,我们直接进行赋值,发现数据已经修改成功,但是页⾯并没有自动渲染成最新的数据;这是为什么呢?

就如同官网所说的reactive存在一些局限性:(官方的描述

原因:

原因就是reactive函数会返回一个Proxy包装的对象,所以当我们这样直接赋值时:(看下面例子)

import { reactive } from "vue";

let userInfo = reactive([{name:'Eula'}]) 
console.log(userInfo) // Proxy(Array) 打印出来是一个Proxy对象 当然具备响应式

// 直接后端数据进行赋值
userInfo = [{name:'优菈'}]
console.log(userInfo)  // [{name:'优菈'}] 可以看出 就是打印出了一个普通的数组 所以不具备响应式

这样赋值的话,就会把Proxy对象给覆盖掉,从而无法触发对应的set和get,最终就会导致丢失掉响应性了;

上面的代码 reactive([{name:'Eula'}]) 创建了一个响应式数组,返回一个Proxy包装的对象由userInfo变量进行存放,但是后面我又把一个普通的数组(也就是后端返回的数据)赋值给userInfo,注意这时userInfo这个变量存放的已经是一个普通的数组了,当然也就不具备响应式了;

所以:对于reactive创建的响应式数据应该避免直接使用=号进行赋值;会覆盖响应式;

解决方案:

一、再封装一层数据,即定义属性名,在后期赋值的时候,对此属性进行直接赋值

再封装一层数据,注意myRenderList 这个属性就是新增的属性用来存放列表数据,就是比较麻烦了一些。

<script setup>
import { reactive, ref } from "vue";
// 定义响应式 
let list1 = reactive({myRenderList:[]});

// 请求的数据
let newList1 = [
  { name: "Eula", age: "18", isActive: false },
  { name: "Umbra", age: "17", isActive: false },
]

// 更改数据
const setList1 = () => {
  list1.myRenderList = newList1
}
</script>

二、使用数组的splice来直接更改原数组

还是用reactive来定义响应式数据,只不过改数据的方式变了,使用数组的原生方法splice()来更改原数组,不是直接覆盖所以并不会影响响应式;

splice有三个参数时,可以对数组进行修改, 第一项是起始索引, 第二项是长度, 第三项是新插入的元素,可以有多个;

下面的代码是把之前数组的每一项删除掉,然后插入新的数据newList1,使用...扩展符进行展开每一项;

 list1.splice(0,list1.length,...newList1)

当然,push()方法也是可以触发响应式的,只不过只能在后面新增数据。还有pop,shift,unshift等方法(用的不多)

<script setup>
import { reactive, ref } from "vue";
// 定义响应式 
let list1 = reactive([]);

// 请求的数据
let newList1 = [
  { name: "Eula", age: "18", isActive: false },
  { name: "Umbra", age: "17", isActive: false },
]

// 更改数据
const setList1 = () => {
  // splice三个参数时 第一项是起始索引  第二项是长度  第三项是新插入的元素,可以有多个
  list1.splice(0,list1.length,...newList1)
}
</script>

三、使用 ref 来定义数据

复杂数据类型也可以使用ref进行定义,而且数据都是响应式的;原理就有点像第一种方式,重新包装了一层value;每次使用的时候都要写.value;

ref实际就是对一个普通值做了一层包装,包装成一个对象,并通过其get和set实现依赖收集和更新,其实现原理类似于computed;

<script setup>
import { reactive, ref } from "vue";
// 定义响应式
let list1 = ref([]);

// 请求的数据
let newList1 = [
  { name: "Eula", age: "18", isActive: false },
  { name: "Umbra", age: "17", isActive: false },
]

// 更改数据
const setList1 = () => {
  list1.value = newList1;
}
</script>
更多推荐

上新!100%国产物料认证,米尔入门级国产核心板全志T113-i方案

自米尔国产全志T113系列的核心板发布以来,这款高性价比、低成本、入门级、高性能的国产核心板咨询不断,配套的开发板已经成交量数百套,深受工程师们的青睐,为了集齐T113全系列的产品,这次米尔发布了基于全志T113-i处理器的核心板和开发板,让广大工程师有了更多的选择。接下来看看这款T113-i国产核心板的性能和优势。M

ETHERNET IP站转CCLKIE协议网关

产品介绍JM-EIP-CCLKIE是自主研发的一款ETHERNET/IP从站功能的通讯网关。该产品主要功能是实现CCLINKIEFB总线和ETHERNET/IP网络的数据互通。本网关连接到ETHERNET/IP总线中做为从站使用,连接到CCLINKIEFB总线中做为从站使用。产品参数技术参数l网关做为ETHERNET/

nginx 安全加固

Nginx官方容器的安全加固主要包括以下几个方面:最小化容器:尽量只包含运行应用程序所需的最小文件和依赖项。这可以减少攻击面,提高安全性。使用非root用户运行容器:默认情况下,Docker容器以root用户身份运行,这可能会带来安全风险。你可以在Dockerfile中使用USER指令来指定一个非root用户运行容器。

人源化抗体的改造方式及其优势

抗体是一类能与抗原特异性结合的免疫球蛋白,作为免疫系统中的重要组成部分,在许多疾病的预防和治疗中发挥着重要作用。抗体治疗的最早应用可以追溯到中国人接种“人痘”预防天花的记载算起,国际上一般公认的人痘接种术最早起源于中国公元10世纪,但据中国的一些史书记载,种痘的兴起更早,始于唐朝。而直到1986年FDA批准了第一个治疗

Python基础之装饰器

文章目录1装饰器1.1定义1.2使用示例1.2.1使用类中实例装饰器1.2.2使用类方法装饰器1.2.3使用类中静态装饰器1.2.4使用类中普通装饰器1.3内部装饰器1.3.1@property2常用装饰器2.1@timer:测量执行时间2.2@memoize:缓存结果2.3@validate_input:数据验证2.

van-button根据参数改变字体颜色,实现高度自定义

本来van-button没有属性去单独自定义字体颜色。通过研究,我发现可以通过:style来实现这一需求。<van-buttonclass="case-btn":color="item.BtnBgColor":style="{color:item.BtnColor}"@click="jumpToUrl(item)">这

linux+c语言杂记(二)

一、在Ubuntu20.04上安装GCC默认的Ubuntu软件源包含了一个软件包组,名称为“build-essential”,它包含了GNU编辑器集合,GNU调试器,和其他编译软件所必需的开发库和工具。想要安装开发工具软件包,以拥有sudo权限用户身份或者root身份运行下面的命令:sudoaptupdatesudoa

RestTmplate

why发送http请求,估计很多人用过httpclient和okhttp,确实挺好用的,而Springweb中的RestTemplate和这俩的功能类似,也是用来发送http请求的,不过用法上面比前面的2位要容易很多。spring框架提供的RestTemplate类可用于在应用中调用rest服务,它简化了与http服务

中小企业如何差异化“生意表达”,成为最了不起的小企业?

当线下营销市场饱和时,及时做好营销线路转型。借助营销SaaS中台系统,转战互联网营销。如今的市场已经不是几十年前随便卖一点新鲜的玩意儿就能火爆的场景了。科技发达了,人们的眼界也开阔了,各式各样,琳琅满目的商品占据了市场空间,生意越来越饱满。竞争趋势激烈,商品同质化现象严重。一些商家企业通过压低价格的方式以获取生存空间,

【Java实战项目】【超详细过程】—— 大饼的图片服务器

目录一.下载前端模板二.展示图片(index.htmll)1.标题2.页面跳转链接3.图片展示引入js和vue依赖:写在html文件的head中js代码:写在html文件中的body中html代码:写在html文件的body中二.删除图片在上面的vue对象app中直接加入一个删除方法将OPEN按钮改成删除按钮四.上传图

Java中的一些不常见的关键字

transient对于transient修饰的成员变量,在类的实例对象的序列化处理过程中会被忽略。因此,transient变量不会贯穿对象的序列化和反序列化,生命周期仅存于调用者的内存中而不会写到磁盘里进行持久化。Java中对象的序列化指的是将对象转换成以字节序列的形式来表示,这些字节序列包含了对象的数据和信息,一个序

热文推荐