• 7.vue组件(二)--双向绑定,父子组件访问


    本文主要说两件事

    1. 如何实现父子组件之间的双向绑定

    2. 父组件如何访问子组件的data,method, 子组件如何访问父组件的data,method等


     一. 如何实现父子组件之间的双向绑定

    案例描述:

    父子组件双向绑定
    父组件有一个message,
    子组件有一个文本框
    让他们两个同步变化

    实现思路:

    1. 子组件接收父组件传递过来的参数
    2. 先实现子组件的双向绑定
    3. 子组件将数据传给父组件

     实现步骤:

    第一步: 子组件接收父组件的data

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="../../js/vue.js"></script>
    </head>
    <body>
        <div id="app">
            父组件的值: {{message}}
            <br>
            <input type="text" v-model="message"></input>
            <comp1 :cmessage="message" ></comp1>
        </div>
    
        <template id="comp1">
            <div style="  600px; background-color: #085e7d; color: antiquewhite">
                <h2>子组件cmessage的值:{{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>

    子组件通过属性props: ["cmessage"], 来接收父组件的message属性. 并且父组件修改message的值, 子组件跟随改变

    效果如下:

     第二步: 实现子组件属性的双向绑定 

     组件的数据绑定, 使用的也是data属性.但在组件中, data定义为一个方法

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="../../js/vue.js"></script>
    </head>
    <body>
        <div id="app">
            父组件的值: {{message}}
            <br>
            <input type="text" v-model="message"></input>
            <comp1 :cmessage="message" ></comp1>
        </div>
    
        <template id="comp1">
            <div style="  600px; background-color: #085e7d; color: antiquewhite">
                <h2>子组件cmessage的值:{{cmessage}}</h2>
                <h2>子组件cmess的值: {{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>

    data中定义了属性cmess, 其值是属性cmessage的值. 我们实现cmess属性的双向绑定.cmess:<input type="text" v-model="cmess" ></input>

     效果如下:

     这样子组件cmess的双向绑定实现了, 但是我们发现修改父组件的时候,子组件没有变化. 修改子组件的时候, 父组件也没有变化

     第三步: 子组件属性变化同步给父组件

    子组件属性的改变同步给父组件, 使用的是自定义事件 

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="../../js/vue.js"></script>
    </head>
    <body>
        <div id="app">
            父组件的值: {{message}}
            <br>
            <input type="text" v-model="message"></input>
            <comp1 :cmessage="message" @csyncchange="syncchange"></comp1>
        </div>
    
        <template id="comp1">
            <div style="  600px; background-color: #085e7d; color: antiquewhite">
                <h2>子组件cmessage的值:{{cmessage}}</h2>
                <h2>子组件cmess的值: {{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>

    添加子组件的input事件: @input="changeMessage".

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

    然后自定义一个csyncchange事件, 父组件监听这个事件的变化 

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

    父组件自定义一个method方法, 接收事件传递的数据

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

    这样就实现了子组件修改cmess的值, 同步给父组件. 效果如下:

     但是, 我们发现,在组建同步给父组件没问题, 组件只同步数据给了props属性, 而没有同步给cmess

    第四步: 使用watch方法监听props属性的变化

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="../../js/vue.js"></script>
    </head>
    <body>
        <div id="app">
            父组件的值: {{message}}
            <br>
            <input type="text" v-model="message"></input>
            <comp1 :cmessage="message" @csyncchange="syncchange"></comp1>
        </div>
    
        <template id="comp1">
            <div style="  600px; background-color: #085e7d; color: antiquewhite">
                <h2>子组件cmessage的值:{{cmessage}}</h2>
                <h2>子组件cmess的值: {{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>

    这一步的重点是watch方法. 同步cmessage的值给cmess. 看看效果

    以上,完美实现了,父子组件的双向数据绑定. 

    二. 父子组件的相互访问

     如果父组件想要访问子组件的属性和方法, 或者子组件想要访问父组件的属性和方法怎么办呢? 下面来看看:

    1. 父组件访问子组件

    父组件访问子组件有两种方式

    • 1. 使用$children
    • 2. 使用@refs

    案例: 现在有一个父组件, 想要拿到子组件的方法或者变量.

    • 使用$children获取

    获取所有的子组件: this.$children
    获取某个子组件的属性: this.$children.属性名
    获取某个子组件的方法: this.$children.方法名()
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <div id="app">
        <h1>第一种方法: 使用children访问子组件</h1>
        <app1-comp></app1-comp>
        <app1-comp></app1-comp>
        <app1-comp></app1-comp>
        <button @click="btnclick">按钮</button>
    
    </div>
    
    <template id="comp1">
        <div>
            <p>只有app1才能使用的组件</p>
            <h2>{{name}}</h2>
        </div>
    </template>
    <script src="../../js/vue.js"></script>
    <script>
        const app1Comp = Vue.extend({
            template: comp1,
            data() {
                return {
                    name : "name名称"
                }
            },
            methods: {
                getchange() {
                    console.log("getchange方法")
                }
            }
    
        })
    
        let app = new Vue({
            el: "#app",
            data: {
                message: "hello"
            },
            components:{
                app1Comp: app1Comp
            },
            methods: {
                btnclick() {
                    console.log("点击事件", this.$children)
                    console.log("父组件访问子组件的data数据: ",this.$children[1].name)
                    console.log("父组件访问子组件的方法: ",this.$children[1].getchange())
    
                }
            }
        });
    
    </script>
    </body>
    </html>

    在dom中使用了三个comp1组件. 我们可以使用this.$children来获取所有的组件

     这里获取到了3个组件, 并打印了第二个组件的名称和方法

    • 使用@refs获取属性

    使用refs的好处是可以根据组件名称获取. 而不是遍历, 因为遍历的下标时可能修改的.

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <!--
        父组件访问子组件有两种方式
        1. 使用$children
        2. 使用@refs
    
        需求: 现在有一个父组件, 想要拿到子组件的方法或者变量.
        所以, 我们先定义一个组件.
    
    -->
    <div id="app">
        <h1>第二种方法: 使用refs访问子组件</h1>
        <app2-comp ref="app21"></app2-comp>
        <app2-comp ref="app22"></app2-comp>
        <app2-comp ref="app23"></app2-comp>
        <button @click="btnclick">按钮</button>
    
    </div>
    
    <template id="comp1">
        <div>
            <p>只有app1才能使用的组件</p>
            <h2>{{name}}</h2>
        </div>
    </template>
    <script src="../../js/vue.js"></script>
    <script>
        const app1Comp = Vue.extend({
            template: comp1,
            data() {
                return {
                    name : "name名称"
                }
            },
            methods: {
                getchange() {
                    console.log("getchange方法")
                }
            }
    
        })
    
        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>

    这一次我们给组件起了名字, 通过$refs可以指定组件名,获取属性和方法

    2. 子组件访问父组件 

    •  子组件访问父组件使用的是$parent
    • 子组件访问根组件使用$root

     通常new Vue()也是一个组件, 他是根组件. 如果子组件想要获取根组件的属性和方法,使用@root

    下面这个例子, 是子组件comp1里面引用了另一个组件comp2. 在comp2中获取comp1的属性和方法, 使用@parent, 这就是子组件获取父组件的属性和方法

    comp2要想获取new Vue()对象的属性和方法, 使用的是$root.

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <!--
        父组件访问子组件有两种方式
        1. 使用$children
        2. 使用@refs
    
        需求: 现在有一个父组件, 想要拿到子组件的方法或者变量.
        所以, 我们先定义一个组件.
    
    -->
    <div id="app">
        <h1>子组件访问父组件</h1>
        <comp1></comp1>
    
    
    </div>
    <template id="comp1">
        <div>
            <comp2></comp2>
        </div>
    
    </template>
    <template id="comp2">
        <div>
            <p>组件comp2</p>
            <button  type="text" @click="btnClick">按钮</button>
        </div>
    </template>
    <script src="../../js/vue.js"></script>
    <script>
        const app1Comp = Vue.extend({
            template: comp1,
            data() {
                return {
                    name: "name名称"
                }
            },
            components: {
                comp2: {
                    template: comp2,
    
                    methods: {
                        btnClick() {
                            console.log(this.$parent)
                            console.log(this.$parent.name)
    
                            // 获取root元素, 也就是vue元素
                            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>

     以上就是父子组件之间相互访问的情况



  • 相关阅读:
    基于Servlet+smartUpload的文件上传
    基于Servlet+smartUpload的文件上传
    基于Servlet+smartUpload的文件上传
    dispatch_async 的 block 中是否该使用_weak self
    dispatch_async 的 block 中是否该使用_weak self
    dispatch_async 的 block 中是否该使用_weak self
    dispatch_async 的 block 中是否该使用_weak self
    Vagrant Tip: Virtualbox Guest Additions
    Vagrant Tip: Virtualbox Guest Additions
    Vagrant Tip: Virtualbox Guest Additions
  • 原文地址:https://www.cnblogs.com/ITPower/p/14455408.html
Copyright © 2020-2023  润新知