Vue3 变换 props 结构保持反应性
我有一个从API获取数据并将其传递给显示它的组件(再次传递到多个子组件)的组件。因此,我试图将这些信息分为多个REF对象,以传递到每个子组件。
问题是,我会失去反应性...新的ref对象不会在父组件更改其数据时更新。
我创建了一个示例来显示问题。
parentComponent
<template>
<p>All data: {{ data }}</p>
<child-component :data="data"></child-component>
</template>
<script setup>
import { ref } from "vue";
import ChildComponent from "./ChildComponent.vue";
let data = ref({
a: {},
b: {},
c: {}, // More properties...
});
setTimeout(() => { // FAKE API
data.value.a = {
name: "prop A",
description: "aaa"
};
data.value.b = {
name: "prop B",
description: "bbb"
};
data.value.c = {
name: "prop C",
description: "ccc"
};
// More properties updated...
}, 2000);
</script>
ChildComponent
<template>
<p>child component props: {{data}}</p>
<p>child component manipulated: {{manipulated}}</p>
</template>
<script setup>
import { ref } from "vue";
const props = defineProps(['data'])
let manipulated = ref({ // Only need a and b properties.
a: props.data.a,
b: props.data.b
})
</script>
输出端子组件
All data: { "a": {}, "b": {}, "c": {} }
child component props: { "a": {}, "b": {}, "c": {} }
child component manipulated: { "a": {}, "b": {} }
在更新后的parent组件数据后输出时输出:
All data: { "a": { "name": "prop A", "description": "aaa" }, "b": { "name": "prop B", "description": "bbb" }, "c": { "name": "prop C", "description": "ccc" } }
child component props: { "a": { "name": "prop A", "description": "aaa" }, "b": { "name": "prop B", "description": "bbb" }, "c": { "name": "prop C", "description": "ccc" } }
child component manipulated: { "a": {}, "b": {} }
更新后的父组件数据后所需的结果:
All data: { "a": { "name": "prop A", "description": "aaa" }, "b": { "name": "prop B", "description": "bbb" }, "c": { "name": "prop C", "description": "ccc" } }
child component props: { "a": { "name": "prop A", "description": "aaa" }, "b": { "name": "prop B", "description": "bbb" }, "c": { "name": "prop C", "description": "ccc" } }
child component manipulated: { "a": { "name": "prop A", "description": "aaa" }, "b": { "name": "prop B", "description": "bbb" } }
如何实现?借助原语的作用...但是有了物体,缺少某些东西来维持反应性...
I have a component that gets data from the API and passes it to another component that displays it (passing down again to multiple child components). So I tried to split that information into multiple ref objects for passing down to each child component.
The problem is, doing that I loose reactivity... the new ref object does not update when parent component changes their data.
I created an example to show the problem.
ParentComponent
<template>
<p>All data: {{ data }}</p>
<child-component :data="data"></child-component>
</template>
<script setup>
import { ref } from "vue";
import ChildComponent from "./ChildComponent.vue";
let data = ref({
a: {},
b: {},
c: {}, // More properties...
});
setTimeout(() => { // FAKE API
data.value.a = {
name: "prop A",
description: "aaa"
};
data.value.b = {
name: "prop B",
description: "bbb"
};
data.value.c = {
name: "prop C",
description: "ccc"
};
// More properties updated...
}, 2000);
</script>
ChildComponent
<template>
<p>child component props: {{data}}</p>
<p>child component manipulated: {{manipulated}}</p>
</template>
<script setup>
import { ref } from "vue";
const props = defineProps(['data'])
let manipulated = ref({ // Only need a and b properties.
a: props.data.a,
b: props.data.b
})
</script>
Output when mount components
All data: { "a": {}, "b": {}, "c": {} }
child component props: { "a": {}, "b": {}, "c": {} }
child component manipulated: { "a": {}, "b": {} }
Output after updated parent component data:
All data: { "a": { "name": "prop A", "description": "aaa" }, "b": { "name": "prop B", "description": "bbb" }, "c": { "name": "prop C", "description": "ccc" } }
child component props: { "a": { "name": "prop A", "description": "aaa" }, "b": { "name": "prop B", "description": "bbb" }, "c": { "name": "prop C", "description": "ccc" } }
child component manipulated: { "a": {}, "b": {} }
Desired result after updated parent component data:
All data: { "a": { "name": "prop A", "description": "aaa" }, "b": { "name": "prop B", "description": "bbb" }, "c": { "name": "prop C", "description": "ccc" } }
child component props: { "a": { "name": "prop A", "description": "aaa" }, "b": { "name": "prop B", "description": "bbb" }, "c": { "name": "prop C", "description": "ccc" } }
child component manipulated: { "a": { "name": "prop A", "description": "aaa" }, "b": { "name": "prop B", "description": "bbb" } }
How can achieve that? With primitives works... but with objects there is missing something to maintain the reactivity...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
![扫码二维码加入Web技术交流群](/public/img/jiaqun_03.jpg)
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
选项 1:使用深度观察程序
您可以使用 深度观察程序(即,
watch
与props.data
上的deep
标志),用props.data
的新值更新manipulated
:演示 1
选项2:使用
compulated
如果
manipulated
只是一个只读道具,你可以从ref
和watch
切换改为计算
:演示 2
Option 1: Use deep watcher
You could use a deep watcher (i.e.,
watch
with thedeep
flag) onprops.data
that updatesmanipulated
with the new values ofprops.data
:demo 1
Option 2: Use
computed
If
manipulated
were just a read-only prop, you could switch from theref
andwatch
to acomputed
instead:demo 2