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