【问题标题】:Vue 3 why is the parent updated when child data changes?Vue 3 为什么在子数据更改时更新父项?
【发布时间】:2023-02-02 18:41:46
【问题描述】:

和这位家长...

<template>
    <h2>Parent</h2>
    {{ parent.a }}
    {{ parent.b }}
    <ChildComponent :data="parent" />
</template>

<script setup>
import { reactive } from 'vue'
import ChildComponent from './components/ChildComponent.vue'
const parent = reactive({ a: 1, b: 2 })
</script>

而这个孩子...

<template>
    <h2>Child component</h2>
    <p>{{ child.a }}</p>
    <p>{{ child.b }}</p>
    <input type="text" v-model="child.b" />
</template>

<script setup>
import { reactive } from 'vue'
const props = defineProps(['data'])
const child = reactive(props.data)
child.a = 'why do i update the parent?'
</script>

为什么要在这里更新父母的数据?我认为随着“数据”道具的绑定是单向的,我需要一个发射器将数据发送回父级吗?相反,对子组件中 child 对象的任何更改都会更新父组件中的 parent 对象。

在文档中说

当对象和数组作为 props 传递时,虽然子组件不能改变 prop 绑定,但它将能够改变对象或数组的嵌套属性。这是因为在 JavaScript 中,对象和数组是通过引用传递的,而 Vue 防止这种突变的代价高得不合理。

但是从我的示例来看,a 和b 没有嵌套?

【问题讨论】:

  • 我可以想到这个语句——reactive 返回对象的一个​​ reactive 副本。反应式转换是“深度”的。建议专门使用反应式代理,避免依赖原始对象。其次,虽然从反应式返回的对象是深度反应式的(为对象设置任何值都会触发 Vue 中的反应)
  • 所以,我的假设是,使用反应式 api 可能是原因。您可以尝试解构反应对象,例如 const parent = {...reactive({ a: 1, b: 2 })} 并检查这是否是罪魁祸首。
  • 感谢您的评论,尽管解构 reactive 将完全失去反应性。你是对的,尽管 reactive 的使用是问题所在 - 因为它正在创建原始的反应副本..我会添加一个答案。

标签: vue.js vuejs3


【解决方案1】:

进一步阅读,我发现问题在于对孩子使用reactive。它正在创建原始副本(参考)的反应副本,因此对副本的任何更新都会影响两者。我需要改用ref:

<template>
    <div>
        <h2>Child component</h2>
        <p>{{ a }}</p>
        <p>{{ b }}</p>
        <input type="text" v-model="b" />
    </div>
</template>

<script setup>
import { ref } from 'vue'
const props = defineProps(['data'])

const a = ref(props.data.a)
const b = ref(props.data.b)
</script>

【讨论】:

    【解决方案2】:

    子组件更新父值的原因是双向数据绑定。您可以通过在子组件内创建对象的副本然后使用复制的版本来解决此问题。

    【讨论】:

    • 我可能会误解,但为什么会这样然后文档说:“所有道具在子属性和父属性之间形成单向向下绑定:当父属性更新时,它将流向子属性,但反之则不然。”
    猜你喜欢
    • 2020-10-26
    • 2020-12-13
    • 1970-01-01
    • 2021-06-16
    • 1970-01-01
    • 1970-01-01
    • 2018-08-24
    • 1970-01-01
    • 2019-01-30
    相关资源
    最近更新 更多