With this parent...
<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>
And this child...
<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>
Why is the data on the parent being updated here? I thought that with binding of the 'data' prop being one-way, I would need an emit to send the data back to the parent? Instead any changes to the child
object in the child component is updating the parent
object in the parent.
In the documentation it says
When objects and arrays are passed as props, while the child component cannot mutate the prop binding, it will be able to mutate the object or array's nested properties. This is because in JavaScript objects and arrays are passed by reference, and it is unreasonably expensive for Vue to prevent such mutations.
But from my example, a
and b
aren't nested?
CodePudding user response:
Further reading and I've found that it's the use of reactive
on the child that is the issue. It is creating a reactive copy of the original (a reference), so any updates to the copy were affecting both. I needed to use ref
instead:
<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>
CodePudding user response:
The reason why child component is updating parent values is the two way data binding. You can solve this problem by creating a copy of an object inside a child component and then use the copied version.