preface

Bidirectional binding between parent and child components is very simple, but many people may not know how to bidirectional binding since they started using Vue 2+. Of course, the simplest bidirectional binding (in a single file) is the V-Model of form elements. For example, responds to the value attribute of the form element. When the text of the input field changes, the value value is passed to the variable bound to the V-model. If v-model and value are set at the same time, the value attribute is invalid.

Custom bidirectional parent-child componentsv-model

When several DOM’s are wrapped into components, we need to customize the V-Model rules we want when we use the child component in the parent but cannot use the V-Model on the child component tag because the child component tag is not a form element.

<! -- children.vue -->
<template>
    <h1>{{ msg }}</h1>
</template>
<script>

export default{
    model: {prop:'msg'.// This field refers to the MSG that the parent component passes to the child component when setting the V-model
        event:'parent-event'// This field indicates that the parent component listens for parent-event events
    },
    props: {msg:String // The same props as the Prop of the model must be defined here, because the V-Model will pass values to the child components
    },
    mounted(){
    // The MSG is sent asynchronously to the parent component v-model to achieve bidirectional control
        setTimeout(_= >{
            let some = 'Some value after 3 seconds';// Some value of the child component itself
            this.$emit('parent-event',some);
            // Emit this value to trigger parent-event, passing some to the v-model bound variable of the parent component
        },3000); }}</script>
Copy the code
<! -- parent.vue -->
<template>
    <children v-model="parentMsg"></children>
</template>
<script>
import children from 'path/to/children.vue';
export default{
    components:{
        children
    },
    data(){
        return{
            parentMsg:'test'}},watch: {parentMsg(newV,oldV){
            console.log(newV,oldV);
            // The console will output in three seconds
            //' some value after 3 seconds ','test'}}}</script>
Copy the code

Have you learned the component’s custom V-Model yet? If it is a normal form element, you can also listen for the form’s input or change event and pass value or Checked via $emit in real time.

Custom multiple bidirectional values for the parent component

The above example implements bidirectional binding of a single prop value, when the requirements of the component require complex operations that require multiple bidirectional values. We need the.sync modifier, which was abandoned by Vue and has since returned.

In fact, this ratiov-modelMore simple

<! -- children.vue -->
<template>
    <h1>{{ msg }}</h1>
</template>
<script>

export default{
    props: {msg:String
    },
    mounted(){
    // The MSG is sent asynchronously to the parent component v-model to achieve bidirectional control
        setTimeout(_= >{
            let some = 'Some value after 3 seconds';// Some value of the child component itself
            this.$emit('update:msg',some);
            // Pass this value through emit
            // Update is a fixed field, passing some to the parent component's V-model bound variable by concatenating the bidirectional bound MSG with a colon
        },3000); }}</script>
Copy the code
<! -- parent.vue -->
<template>
    <children :msg.sync="parentMsg"></children>
    <! -- add the.sync modifier to the usual one-way value -->
</template>
<script>
import children from 'path/to/children.vue';
export default{
    components:{
        children
    },
    data(){
        return{
            parentMsg:'test'}},watch: {parentMsg(newV,oldV){
            console.log(newV,oldV);
            // The console will output in three seconds
            //' some value after 3 seconds ','test'}}}</script>
Copy the code

To note here, although plus. Sync can be a two-way binding, but still want to rely on child components $emit to trigger the update: modify the parent component of a variable’s value prop of realizing bidirectional data flow, if direct direct assignment, the property of prop will still appear error.

In fact,.syncA modifier is a shorthand that does one thing

<template>
    <children :msg.sync="parentMsg"></children>
    <! -- equivalent to -->
    <children :msg="parentMsg" @update:msg="parentMsg = $event"></children>
    <! $emit = $emit; $emit = $emit;
</template>
Copy the code

When you need to pass all attributes of an object.syncWhen passing in a bidirectional data stream, we can write it in a simpler way

<template>
    <children :.sync="obj"></children>
</template>
<script>
export default{
    components:{
        children
    },
    data(){
        return{
            obj: {parentMsg:'test'}}}}</script>
Copy the code

When this notation is used, all properties in the obj object are passed to the child component through separate props, and the corresponding update: is listened for, and the corresponding props are declared in the child component as well.

conclusion

In parent-child components, using two-way data streams can be a great experience at times, but it must be used in moderation, as two-way data streams can add to the maintenance burden later in the project.

Sharing goes a long way.