vue component -- bidirectional binding, parent-child component access

This article mainly talks about two things

1. How to realize bidirectional binding between parent and child components

2. How the parent component accesses the data and method of the child component, and how the child component accesses the data and method of the parent component

I How to realize bidirectional binding between parent and child components

Case description:

Two way binding of parent and child components
 Parent component has one message,
The subcomponent has a text box
 Let the two of them change synchronously

 

Realization idea:

1. The child component receives the parameters passed by the parent component
2. First, implement the two-way binding of sub components
3. The child component passes the data to the parent component

Implementation steps:

Step 1: the child component receives the data of the parent component

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../../js/vue.js"></script>
</head>
<body>
    <div id="app">
        Value of parent component: {{message}}
        <br>
        <input type="text" v-model="message"></input>
        <comp1 :cmessage="message" ></comp1>
    </div>

    <template id="comp1">
        <div style=" width: 600px; background-color: #085e7d; color: antiquewhite">
            <h2>Subcomponents cmessage Value of:{{cmessage}}</h2>
            <br>
        </div>
    </template>
    <script>
        Vue.component("comp1", {
            template: "#comp1",
            props: ["cmessage"],

        })
        const app = new Vue({
            el: "#app",
            data: {
                message: "hello"
            }
        });
    </script>
</body>
</html>

The child component receives the message attribute of the parent component through the attribute props: ["cmessage"] And the parent component modifies the value of message, and the child component changes accordingly

The effect is as follows:

 

Step 2: realize the two-way binding of sub component attributes

The data binding of component also uses the data attribute But in the component, data is defined as a method

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../../js/vue.js"></script>
</head>
<body>
    <div id="app">
        Value of parent component: {{message}}
        <br>
        <input type="text" v-model="message"></input>
        <comp1 :cmessage="message" ></comp1>
    </div>

    <template id="comp1">
        <div style=" width: 600px; background-color: #085e7d; color: antiquewhite">
            <h2>Subcomponents cmessage Value of:{{cmessage}}</h2>
            <h2>Subcomponents cmess Value of: {{cmess}}</h2>
            <br>
            cmess:<input type="text"  v-model="cmess" ></input>
            <br>
        </div>
    </template>
    <script>
        Vue.component("comp1", {
            template: "#comp1",
            props: ["cmessage"],
            data() {
                return {
                    "cmess": this.cmessage
                }
            }

        })
        const app = new Vue({
            el: "#app",
            data: {
                message: "hello"
            }
        });
    </script>
</body>
</html>

The attribute cmessage is defined in data, and its value is the value of the attribute cmessage We implement the bidirectional binding of cmess attribute cmess:<input type="text" v-model="cmess" ></input>

The effect is as follows:

 

In this way, the two-way binding of component cmess is implemented, but we find that when modifying the parent component, the child component does not change When modifying a child component, the parent component does not change

Step 3: synchronize the attribute changes of the child component to the parent component

The changes of child component properties are synchronized to the parent component, using custom events

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../../js/vue.js"></script>
</head>
<body>
    <div id="app">
        Value of parent component: {{message}}
        <br>
        <input type="text" v-model="message"></input>
        <comp1 :cmessage="message" @csyncchange="syncchange"></comp1>
    </div>

    <template id="comp1">
        <div style=" width: 600px; background-color: #085e7d; color: antiquewhite">
            <h2>Subcomponents cmessage Value of:{{cmessage}}</h2>
            <h2>Subcomponents cmess Value of: {{cmess}}</h2>
            <br>
            cmess:<input type="text"  v-model="cmess"  @input="changeMessage"></input>
            <br>
        </div>
    </template>
    <script>
        Vue.component("comp1", {
            template: "#comp1",
            props: ["cmessage"],
            data() {
                return {
                    "cmess": this.cmessage
                }
            },
            methods: {
                changeMessage(event) {
                    console.log(event.target.value)
                    this.$emit("csyncchange", event.target.value)
                }
            },
            watch: {
                cmessage(val, oldval) {
                    console.log(val, oldval)
                    console.log()
                    this.cmess = val
                }
            }

        })
        const app = new Vue({
            el: "#app",
            data: {
                message: "hello"
            },
            methods: {
                syncchange(value) {
                    this.message = value
                }
            }
        });
    </script>
</body>
</html>

 

 

Add input event of sub component: @ input="changeMessage"

changeMessage(event) {
    console.log(event.target.value)
    this.$emit("csyncchange", event.target.value)
}

Then customize a csyncchange event, and the parent component listens to the change of this event

<comp1 :cmessage="message" @csyncchange="syncchange"></comp1>

The parent component defines a method method to receive the data passed by the event

methods: {
    syncchange(value) {
        this.message = value
    }
}    

This enables the child component to modify the value of cmess and synchronize it with the parent component The effect is as follows:

 

However, we found that it is no problem to synchronize the data to the parent component in the build. The component only synchronizes the data to the props attribute, not to cmess

Step 4: use the watch method to monitor the changes of props attribute

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../../js/vue.js"></script>
</head>
<body>
    <div id="app">
        Value of parent component: {{message}}
        <br>
        <input type="text" v-model="message"></input>
        <comp1 :cmessage="message" @csyncchange="syncchange"></comp1>
    </div>

    <template id="comp1">
        <div style=" width: 600px; background-color: #085e7d; color: antiquewhite">
            <h2>Subcomponents cmessage Value of:{{cmessage}}</h2>
            <h2>Subcomponents cmess Value of: {{cmess}}</h2>
            <br>
            cmess:<input type="text"  v-model="cmess"  @input="changeMessage"></input>
            <br>
        </div>
    </template>
    <script>
        Vue.component("comp1", {
            template: "#comp1",
            props: ["cmessage"],
            data() {
                return {
                    "cmess": this.cmessage
                }
            },
            methods: {
                changeMessage(event) {
                    console.log(event.target.value)
                    this.$emit("csyncchange", event.target.value)
                }
            },
            watch: {
                cmessage(val, oldval) {
                    console.log(val, oldval)
                    console.log()
                    this.cmess = val
                }
            }

        })
        const app = new Vue({
            el: "#app",
            data: {
                message: "hello"
            },
            methods: {
                syncchange(value) {
                    this.message = value
                }
            }
        });
    </script>
</body>
</html>

The focus of this step is the watch method Synchronize the value of cmessage to cmessage See the effect

 

Above, the bidirectional data binding of parent and child components is perfectly realized  

II Mutual access between parent and child components

What if the parent component wants to access the properties and methods of the child component, or the child component wants to access the properties and methods of the parent component? Let's take a look:

1. Parent component accesses child component

There are two ways for parent components to access child components

  • 1. Use $children
  • 2. Use @ refs

 

Case: now there is a parent component that wants to get the methods or variables of the child component

  • Get with $children

Get all sub components: this.$children
 Get the properties of a subcomponent: this.$children.Attribute name
 Method to get a subcomponent: this.$children.Method name()
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <h1>The first method: use children Access subcomponents</h1>
    <app1-comp></app1-comp>
    <app1-comp></app1-comp>
    <app1-comp></app1-comp>
    <button @click="btnclick">Button</button>

</div>

<template id="comp1">
    <div>
        <p>only app1 Components that can be used</p>
        <h2>{{name}}</h2>
    </div>
</template>
<script src="../../js/vue.js"></script>
<script>
    const app1Comp = Vue.extend({
        template: comp1,
        data() {
            return {
                name : "name name"
            }
        },
        methods: {
            getchange() {
                console.log("getchange method")
            }
        }

    })

    let app = new Vue({
        el: "#app",
        data: {
            message: "hello"
        },
        components:{
            app1Comp: app1Comp
        },
        methods: {
            btnclick() {
                console.log("Click event", this.$children)
                console.log("Access of parent component to child component data data: ",this.$children[1].name)
                console.log("The method by which a parent component accesses a child component: ",this.$children[1].getchange())

            }
        }
    });

</script>
</body>
</html>

Three comp1 components are used in dom We can use this$ Children to get all the components

 

Here, three components are obtained, and the name and method of the second component are printed

  • Get properties using @ refs

The advantage of using refs is that it can be obtained according to the component name Instead of traversal, because the subscript of traversal may be modified

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--
    There are two ways for parent components to access child components
    1. use $children
    2. use@refs

    demand: There is now a parent component, Want to get the method or variable of the sub component.
    therefore, Let's define a component first.

-->
<div id="app">
    <h1>The second method: use refs Access subcomponents</h1>
    <app2-comp ref="app21"></app2-comp>
    <app2-comp ref="app22"></app2-comp>
    <app2-comp ref="app23"></app2-comp>
    <button @click="btnclick">Button</button>

</div>

<template id="comp1">
    <div>
        <p>only app1 Components that can be used</p>
        <h2>{{name}}</h2>
    </div>
</template>
<script src="../../js/vue.js"></script>
<script>
    const app1Comp = Vue.extend({
        template: comp1,
        data() {
            return {
                name : "name name"
            }
        },
        methods: {
            getchange() {
                console.log("getchange method")
            }
        }

    })

    let app = new Vue({
        el: "#app",
        data: {
            message: "hello"
        },
        components:{
            app1Comp: app1Comp,
            app2Comp: app1Comp
        },
        methods: {
            btnclick() {

                console.log(this.$refs.app21.name)
                console.log(this.$refs.app21.getchange())
            }
        }
    });

</script>
</body>
</html>

This time, we named the component. Through $refs, we can specify the component name and obtain properties and methods

 

 

2. The child component accesses the parent component

  • The child component accesses the parent component using $parent
  • The sub component accesses the root component using $root

Usually, new Vue() is also a component, which is the root component If the sub component wants to get the properties and methods of the root component, use @ root

In the following example, the sub component comp1 refers to another component comp2 Obtain the properties and methods of comp1 in comp2, and use @ parent, which is the child component to obtain the properties and methods of the parent component

To get the properties and methods of the new Vue() object, comp2 uses $root

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--
    There are two ways for parent components to access child components
    1. use $children
    2. use@refs

    demand: There is now a parent component, Want to get the method or variable of the sub component.
    therefore, Let's define a component first.

-->
<div id="app">
    <h1>Child component access parent component</h1>
    <comp1></comp1>


</div>
<template id="comp1">
    <div>
        <comp2></comp2>
    </div>

</template>
<template id="comp2">
    <div>
        <p>assembly comp2</p>
        <button  type="text" @click="btnClick">Button</button>
    </div>
</template>
<script src="../../js/vue.js"></script>
<script>
    const app1Comp = Vue.extend({
        template: comp1,
        data() {
            return {
                name: "name name"
            }
        },
        components: {
            comp2: {
                template: comp2,

                methods: {
                    btnClick() {
                        console.log(this.$parent)
                        console.log(this.$parent.name)

                        // obtain root element, that is vue element
                        console.log(this.$root)
                        console.log(this.$root.message)
                    }
                }
            }
        }
    })

    let app = new Vue({
        el: "#app",
        data: {
            message: "hello"
        },
        components:{
            comp1: app1Comp
        },
        methods: {
            btnclick() {

            }
        }
    });

</script>
</body>
</html>

 

The above is the mutual access between parent and child components

 

Tags: Vue

Posted by frikikip on Thu, 14 Apr 2022 11:07:57 +0930