Vue3中响应式丢失情况(版本3.3.4)以及解决方案

518 阅读1分钟
1、解构proxy响应式对象
<template>
<a-button @click="add">add</a-button>

<div>{{ a }}</div>
<div>{{ b.c }}</div>
</template>
<script setup lang="ts">

let proxy = reactive({
  a: 1,
  b: {
     c: 2
  }
})
let { a, b } = proxy;

function add() {
  a++;
  b.c = 5
}
</script>

只有a属性时,a(基本数据类型)失去响应式,很神奇。有b存在时,b和a都具有响应式。 我们在图下可以看到b是一个响应式对象,a不是 image.png

解决方案

使用toRefs,消费者组件可以解构/展开返回的对象而不会失去响应性
(vue官网解释)

let { a } = toRefs(proxy);

function add() {
  a.value++;
}
2、reactive定义的变量直接赋值(数组、对象等)
<template>
  <a-button @click="change">add</a-button>

  <div>{{ proxy.a }}</div>
  <div>{{ proxy.b.c }}</div>
</template>
<script setup lang="ts">
let proxy = reactive({
  a: 1,
  b: {
    c: 2,
  },
});
function change() {
  proxy = {
    a: 2,
    b: {
      c: 5
    }
  };
}
</script>

我们在工具中可以看到proxy的值没有任何变化 image.png
场景复现:我们在初始化的时候,数据为空,调用接口后赋值,此时无法赋值成功

解决方案
  • 使用ref声明对象
<template>
  <a-button @click="change">add</a-button>

  <div>{{ proxy.a }}</div>
  <div>{{ proxy.b.c }}</div>
</template>
<script setup lang="ts">
let proxy = ref({
  a: 1,
  b: {
    c: 2,
  },
});
function change() {
  proxy.value = {
    a: 2,
    b: {
      c: 5
    }
  };
}
</script>
  • 不直接赋值,包裹一层
<template>
  <a-button @click="change">add</a-button>

  <div>{{ proxy.data.a }}</div>
  <div>{{ proxy.data.b.c }}</div>
</template>
<script setup lang="ts">
let proxy = reactive({
  data: {
    a: 1,
    b: {
      c: 2,
    },
  }
});
function change() {
  proxy.data = {
    a: 2,
    b: {
      c: 5
    }
  };
}
</script>
其他

其他实际业务中响应式丢失的情况,可以借助 computed() 来实现