ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

vue3中当用reactive()中定义的对象再次赋值,页面不会自动更新解决方法

2022-05-24 14:04:07  阅读:436  来源: 互联网

标签:info form value reactive 自动更新 vue3 ref 赋值


在vue3里,ref和reacitve都可以定义响应式数据,但是两者有所不同。在使用reactive定义复杂结构的响应式数据时,如果你要对其赋值,会丢失其响应性。然后赋值是我们经常进行的操作,那么该怎么解决呢?

问题:reactive定义的数据不能直接赋值

下述代码会报错: Cannot assign to "form" because it is a constant

//申明表单对象
const form = reactive({

id: undefined,
    name: undefined,
    ...
  })
//通过axios读取数据
  getData(id).then((res) => {
        const { code, data } = res
        if (code == 200) {
          form = {             ...data,           }
        }
     })
   }

 

解决方法

1. 改为ref定义

const form= ref({})
form.value = {...data}

2. 如果是数组的话,可以使用push新增数据

const arr = reactive([])
arr.push(...[1, 2, 3])

3.再封装一层数据(推荐!)即定义属性名,在后期赋值的时候,对属性名进行赋值

const state = reactive({
  arr: [],
form:{} }); state.arr = [1, 2, 3]
state.form = {...data}

但是这样的话在html模板里,使用数据就得state.arr
所以我们可以用解构将它return出来(script setup 里面 不需要return 结构出来即可)

但是reactive解构出来的数据会丢失响应性
所以再用 toRefs()方法为它们添加响应性
最终为:

const state = reactive({
  arr: [],
  form:{}
}); 
state.arr = [1, 2, 3]
state.form ={...data}
return{ ...toRefs(state), }

//如果是在 script setup 里面 不需要return 结构出来即可

const { form,arr} = toRefs(state)
 

4.其他,参考下述转载的方式

优雅的解决reactive()响应式对象初始化重新赋值问题

代码里写了注意点,此处也先声明注意事项:

template 里必须绑定的是 ref() 数据源 !!

重新初始化整个响应式对象时,用来数据操作的实际变量(例子里的info)也需要重新赋值!

这是vue3没正式发布解决 ref() `.value` 的语法糖的相对方案。正式敲定且发布后应该就可废弃我这方案了。

为什么不用 Object.assign() 处理reactive()? 什么情况下用 Object.assign() 处理reactive()?

Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象分配(赋值)到目标对象。所以无法对例子里新增加的数据newKey清除掉!(这种问题常见于从后端接口获得的数据,有时候有{}值,有时候null)。此时不可用 Object.assign()

严格定义对象的interface类型,确保数据完全在掌握范围内,可用 Object.assign()。

此方案解决的痛点:

const info = reactive() ,当info需要重新初始化时,需要用Object.assign(),但是Object.assign() 本质是合并对象并返回结果的新对象。用作初始化数据会导致潜在的问题,尤其是数据非前端可控的情况下(例如接口获得的数据)
所以用ref声明,.value 赋值重新覆盖,才是最稳妥的初始化!(而且这种方法不用担心各种额外因素,降低心智负担~~)
如果用ref.value存储响应式对象,操作起来每次要.value也会很麻烦。 解决这个问题的代码就是对应的 let info = xx 和 初始化的 info = xx 这两行代码!
数组类型的情况下:reactive([1,2]),重新赋值导致丢失响应,ref.value操作也不太方便,因此也可采用这方法。(或者说引用类型目前都可采用这方法)
————————————————

<template lang="">
  <div>
    {{infoRef.newKey}}
    {{infoRef.bar}}
  </div>
</template>
<script lang='ts' setup>
import { ref,reactive } from 'vue';
 
const infoRef = ref<any>(source()) // template 里必须绑定的是 infoRef 不能是 info !!
let info = infoRef.value // Js里操作只操作 info 就可以不用 infoRef.value 了
function reset(){
  // 这样需要重置整个响应式对象就不需要 Object.assign和考虑深拷贝问题了
  infoRef.value = source()
  // 重新初始化整个响应式对象时,用来数据操作的实际变量也需要重新赋值!
  info = infoRef.value
}
function source(){
  return {
    foo:1,
    bar:2,
    obj:{a:1}
  }
}
 
// 测试
setTimeout(() => {
  info.bar *= 110
  info.newKey = 666
}, 3000);
setTimeout(() => {
  reset()
}, 6000);
setTimeout(() => {
  info.bar = 987654321
}, 8000);
</script>

 

 

参考链接:https://blog.csdn.net/qq_38974163/article/details/122426426

                  https://blog.csdn.net/lijiahui_/article/details/122999787

标签:info,form,value,reactive,自动更新,vue3,ref,赋值
来源: https://www.cnblogs.com/riddly/p/16305280.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有