SoFunction
Updated on 2025-04-05

Detailed explanation of the best way to synchronize the state of vue parent-child components

hello! Hello everyone! I am Papaya Taixiang, an old front-end engineer. When we use vue development, we may encounter situations where the parent component and the child component need to be synchronized. Usually this is because when we encapsulate components, there is a same state to use outside and inside. Today we will see how to solve this problem elegantly!
Generally speaking, when we implement this function, we only need the parent component to pass it to the child component through props, but the ideal is full and the reality is skinny. If we change the props directly in the child component, if nothing unexpected happens, the browser will give you a big red error, because in vue, our data flow is top-down, while the props directly in the child component are bottom-up data flow, which is not allowed by vue.

So our solution is that the parent component passes state to the child component through props, and the child component initializes another internal state through props. After each change of the state, the child component notifies the parent component, and then the parent component changes its own state. In fact, it is the application of props on emit. Next, let's start the code.

Parent component

<template>
  <div class="father">
    <h1>The status of parent component maintenance:{{food}}</h1>
    <son :food="food" @update:food="f => food = f"></son>
  </div>
</template>

Subcomponents

<template>
  <div class="son">
    <h2>Status maintained in subcomponents:{{innerFood}}</h2>
    <button @click="innerFood = '100 pounds of beef'">Click to change the status of the subcomponent</button>
  </div>
</template>
<script>
  export default {
    data () {
     return {
       innerFood: 
     } 
    },
    props: {
      food: String
    },
    watch: {
      innerFood (nv) {
        this.$emit("update:food",nv)
      }
    }
  }
</script>

You can see that the above writing method is actually maintaining two different states in the parent and child component. The work we do is just synchronize these two states. There is no problem with this writing method. In fact, we can also implement the part of the child component through computed. Let’s take a look at another method to maintain synchronous state in the subcomponent:

Another way to write subcomponents

<template>
  <div class="son">
    <h2>Status maintained in subcomponents:{{innerFood}}</h2>
    <button @click="innerFood = '100 pounds of beef'">Click to change the status of the subcomponent</button>
  </div>
</template>
<script>
  export default {
    props: {
      food: String
    },
    computed: {
      innerFood: {
        get () {
          return 
        },
        set (nv) {
          this.$emit("update:food",nv)
        }
      }
    }
  }
</script>

Okay, we have demonstrated both ways of writing. Now let’s optimize the way of writing in the parent component.

In the parent component, we can see that we have bound an update:food event on it before and used the arrow function to make an assignment. In fact, we can optimize it slightly here and do not directly assign the arrow function, because we trigger a custom event, and the first parameter we give when triggering is the new value. We can get this value directly through $event, so it can be written in the following form:

Optimized parent component

<template>
  <div class="father">
    <h1>The status of parent component maintenance:{{food}}</h1>
    <son :food="food" @update:food="food = $event"></son>
  </div>
</template>

You think it's over here? In fact, we can go one step closer. As long as we meet the above event naming method, we can actually use the sync modifier instead of event binding, that is, we don’t need to write event binding, but event triggers inside subcomponents still cannot be missing. The final optimization result is as follows:

<template>
  <div class="father">
    <h1>The status of parent component maintenance:{{food}}</h1>
    <son :="food"></son>
  </div>
</template>

At this point, we really complete the synchronization of parent-child components. Of course, maintaining a state in the child component is not necessarily necessary. If we only use the props passed to us by the parent component, and the child component does not directly change the props, then we do not have to create another state in the child component. When our child component wants to change it, we only need to submit the appropriate event at the right time. However, there is a situation where we have to create another state in the child component, that is, when the state passed by our parent component is used in the child component, such as v-model, this two-way data binding function, since v-model will automatically change the value, it is inappropriate to directly fill in the props accepted from the parent component.

This is the article about the best way to synchronize the state of vue parent-child component. For more related content, please search for my previous article or continue browsing the related articles below. I hope everyone will support me in the future!