[Vue] parent child component value transfer

Posted by utherwun on Mon, 24 Jan 2022 19:02:27 +0100

This time without the help of webpack.
In fact, they are all basic things, but they are also very interesting.

Son to father

1. Use $emit to enable the parent component to listen to the methods bound in the child component through v-on

  • Click Button to transfer parameters

  1. Sub component code:
let ChildComponent = {
    data() {
         return {
             childValue: ''
         }
     },
     methods: {
         passValueToFather() {
             this.$emit('get-value', this.childValue);
         }
     },
     template: `
         <div>
             <input v-model="childValue" placeholder="Please enter sub component value">
             <button @click="passValueToFather">Pass value to parent component</button>
         </div>
     `
 };
  1. Parent component code
let FatherComponent = {
    data() {
        return {
            fatherValue: 'Father'
        }
    },
    methods: {
        getValueFromChild(val) {
            this.fatherValue = val;
        }
    },
    template: `
        <div>
            {{ fatherValue }}
            <child-component @get-value="getValueFromChild"></child-component>
        </div>
    `,
    components: {
        'child-component': ChildComponent // Register subcomponents
    }
};
  1. Vue instance initialization
var vm = new Vue({
    el: '#app',
     data: {
         message: 'Hello Vue!'
     },
     components: {
         'father-component': FatherComponent,
     }
 });
  1. HTML reference parent component
<div id="app">
    <father-component>
    </father-component>
</div>

The whole process is as follows
1. Modify values in subcomponents
2. The button in the subcomponent triggers the click event passValueToFather()
3. In the child component, $emit receives the function bound by the parent component through v-on and passes in the value in the child component
4. The parent component binds the function get value declared in $emit through v-on and binds it to the getValueFromChild() method in the parent component methods to obtain the parameter value passed by the child component

  • Enter enter or pass parameters after losing focus

After understanding this process, it is easy to improve on this basis. For example, there is no need to directly change the value of the parent component through a button in the child component.
Bind the @ change event directly in the child component. The implementation effect is to change the parent component value by pressing enter or out of focus in the child component

<div>
   <input
        v-model="childValue" @change="passValueToFather"
        placeholder="Please enter sub component value"
    >
</div>
  • Real time synchronous parameter transmission

If you are more anxious, you can directly monitor the value of the subcomponent through the watch.

template: `
     <div>
         <input
             v-model="childValue"
             placeholder="Please enter sub component value"
         >
     </div> `
 ,
 watch: {
     childValue() {
         this.passValueToFather();
 }

2. Through this$ Refs access

  • Click Button to transfer parameters

A more violent way
This time, we get the value of the child component by clicking the button in the parent component

let FatherComponent = {
     data() {
         return {
             fatherValue: 'Father'
         }
     },
     methods: {
         getChildValue() {
             this.fatherValue = this.$refs.child.$data.childValue;
             // console.log(this.$refs.child.$data.childValue)
         }
     },
     template: `
         <div>
             {{ fatherValue }}
             <button @click="getChildValue">Gets the value of the subcomponent</button>
             <child-component ref="child"></child-component>
         </div>
     `,
     components: {
         'child-component': ChildComponent
     }
 };

You can also assign childValue to fatherValue in the mounted hook function without the help of button. In mounted, refs can only be accessed after the component is rendered.
$refs is not responsive, so if you want to transfer real-time responsive parameters without the help of button s, you can use the next scheme.

3. Listen for the passed value in the subcomponent through this$ Parent dynamic assignment parent component

I suddenly realized when I was writing father to son, so I can manually implement the response.

let ChildComponent = {
      data() {
          return {
              childValue: ''
          }
      },
      template: `
          <div>
              <input v-model="childValue">
          </div>
      `,
      watch: {
          childValue(val) {
              this.$parent.$data.fatherValue = val;
          }
      }
  };

  let FatherComponent = {
      data() {
          return {
              fatherValue: 'Father'
          }
      },
      template: `
          <div>
              {{ fatherValue }}
              <child-component></child-component>
          </div>
      `,
      components: {
          'child-component': ChildComponent
      }
  };

Father to son

A parent-child that follows a one-way data flow is relatively friendly
Define props directly in the child component to receive the value from the parent component

1. Pass parameters by setting props in sub components

In the parent component, v-bind binds the variables corresponding to props in the child component to realize responsive binding and real-time synchronous update

let ChildComponent = {
      template: `
          <div>
              {{ passedValue }}
          </div>
      `,
      props: {
          passedValue: String // Accept parent component parameters
      }
  }

  let FatherComponent = {
      data() {
          return {
              fatherValue: 'Father'
          }
      },
      template: `
          <div>
              <input v-model="fatherValue">
              <child-component :passedValue="fatherValue"></child-component>
          </div>
      `,
      components: {
          'child-component': ChildComponent
      }
  };

2. Change the value of subcomponents in real time through $children or $refs

  • Through $children
    Because $children directly obtains all sub component arrays, it feels that it is not very stable in this way
let ChildComponent = {
     data() {
         return {
             childValue: ''
         }
     },
     template: `
         <div>
             {{ childValue }}
         </div>
     `,
 }

 let FatherComponent = {
     data() {
         return {
             fatherValue: 'Father'
         }
     },
     template: `
         <div>
             <input v-model="fatherValue">
             <child-component></child-component>
         </div>
     `,
     components: {
         'child-component': ChildComponent
     },
     watch: {
         fatherValue(val) {
             this.$children[0].$data.childValue = val;
         }
     }
 };


My God, I didn't understand until I wrote this. I was wrong all the time. I always think that the parent passes on the child to get the father's value through $parent in the child component. In this way, we can't achieve responsiveness.
In fact, the parent and child should listen for the transmitted value in the parent component and assign it to the child component dynamically.
cry and shed bitter tears. He also changed the above father to son.

  • Via $refs
    The sub components are the same as those implemented above through $children and do nothing
    It is also a good real-time response update!
let FatherComponent = {
     data() {
         return {
             fatherValue: 'Father'
         }
     },
     template: `
         <div>
             <input v-model="fatherValue">
             <child-component ref="child"></child-component>
         </div>
     `,
     components: {
         'child-component': ChildComponent
     },
     watch: {
         fatherValue(val) {
             this.$refs.child.$data.childValue = val;
         }
     }
 };

Add event bus next time!

Topics: Vue