vue3解构失去响应式!!!

1,001 阅读2分钟

在 Vue 3 中,props 是响应式的对象。当我们在解构 props 属性时,本质上是创建了新的局部变量,这些变量不再和原始的响应式 props 对象绑定。显然,这些变量失去了原有的响应式,不能跟着 props 的变化而更新,自然拿不到最新的值。

举个例子👇:

父组件中定义:

const person = ref({ name: 'John', age: 30 });
// 引用子组件
<ChildComp :person="person" />

子组件中使用:

const {name, age} = defineProps({
    person: Object,
});

看结果👇:

错误的demo.gif nameage没变呢😫!因为结构使props中的属性拾取了响应式!!!

Vue 的响应式原理:

  • Vue3 的响应式系统是基于 Proxy来实现的
  • props 对象本身是一个响应式对象(Proxy 包装的)

当我们解构这个对象时,实际上是从这个 Proxy 对象中提取了普通的值:

// 这样写会失去响应性
const {name, age} = defineProps({
    person: Object,
});
// 相当于:
const person = props.person // person 现在只是一个普通值的拷贝

举个🌰:

// 响应式对象
const state = reactive({ count: 0 })

// 解构后
const { count } = state
console.log(count) // 0

state.count = 1
console.log(count) // 仍然是 0,因为 count 只是一个普通的值

那怎么办呢🤷

解决方法

  1. 方法一:不结构,直接使用。
// 方法1:直接使用 props.person
const props = defineProps({ person: Object })
// 使用 props.person
  1. 方法二:使用 toRef 保持响应性。toRef 将响应式对象的某个属性转换为一个独立的、响应式的 ref 对象。这样可以在保持响应性的同时单独使用某个属性。
// 方法2:使用 toRef 保持响应性
const props = defineProps({
    person: Object,
});
const person = toRef(props, 'person');
  1. 方法三:使用 toRefs 保持响应性。toRefs 将整个对象的每个属性都转换为 ref。
// 方法3:使用 toRefs 保持响应性
const props = defineProps({
    person: Object,
});
const {name, age} = toRefs(props);

效果⬇️:

正确的toRef.gif

问题解决!