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


    问题:

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

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

    原因:

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

    1. import { reactive } from "vue";
    2. let userInfo = reactive([{name:'Eula'}])
    3. console.log(userInfo) // Proxy(Array) 打印出来是一个Proxy对象 当然具备响应式
    4. // 直接后端数据进行赋值
    5. userInfo = [{name:'优菈'}]
    6. console.log(userInfo) // [{name:'优菈'}] 可以看出 就是打印出了一个普通的数组 所以不具备响应式

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

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

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

    解决方案:

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

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

    1. <script setup>
    2. import { reactive, ref } from "vue";
    3. // 定义响应式
    4. let list1 = reactive({myRenderList:[]});
    5. // 请求的数据
    6. let newList1 = [
    7. { name: "Eula", age: "18", isActive: false },
    8. { name: "Umbra", age: "17", isActive: false },
    9. ]
    10. // 更改数据
    11. const setList1 = () => {
    12. list1.myRenderList = newList1
    13. }
    14. </script>

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

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

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

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

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

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

    1. <script setup>
    2. import { reactive, ref } from "vue";
    3. // 定义响应式
    4. let list1 = reactive([]);
    5. // 请求的数据
    6. let newList1 = [
    7. { name: "Eula", age: "18", isActive: false },
    8. { name: "Umbra", age: "17", isActive: false },
    9. ]
    10. // 更改数据
    11. const setList1 = () => {
    12. // splice三个参数时 第一项是起始索引 第二项是长度 第三项是新插入的元素,可以有多个
    13. list1.splice(0,list1.length,...newList1)
    14. }
    15. </script>

    三、使用 ref 来定义数据

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

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

    1. <script setup>
    2. import { reactive, ref } from "vue";
    3. // 定义响应式
    4. let list1 = ref([]);
    5. // 请求的数据
    6. let newList1 = [
    7. { name: "Eula", age: "18", isActive: false },
    8. { name: "Umbra", age: "17", isActive: false },
    9. ]
    10. // 更改数据
    11. const setList1 = () => {
    12. list1.value = newList1;
    13. }
    14. </script>
  • 相关阅读:
    【LeetCode】1898. 可移除字符的最大数目
    nSum问题解题套路4.5-4.6
    值得收藏的30道Python练手题(附详解)
    Java内部类详解
    牛客网专项练习30天Pytnon篇第01天
    基于JavaSwing开发MP3音乐播放器系统 课程设计 大作业源码 毕业设计
    聊聊Java 序列化和反序列化为什么要实现 Serializable 接口?
    数学建模学习(84):鲸鱼优化算法(WOA)对多目标函数的优化求解
    keras实现深度神经网络,keras实现卷积神经网络
    AIGC如何搞副业专栏更新了!
  • 原文地址:https://blog.csdn.net/Dream_travelerly/article/details/132903468