前端vue开发之二---双向绑定,父子组件访问

news/2024/7/24 11:19:21 标签: vue, 组件化, vue.js, 前端, 经验分享

实际应用项目:http://github.crmeb.net/u/long

 

本文主要说两件事

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=" width: 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=" width: 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=" width: 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=" width: 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>

复制代码

 

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


http://www.niftyadmin.cn/n/908821.html

相关文章

[Log]ASP.NET之HttpModule拦截404异常

Httpmodule代码&#xff1a; public class Error404Module : IHttpModule{public void Init(HttpApplication context){context.Error new EventHandler(Context_Error);}protected void Context_Error(object sender, EventArgs e){HttpContext ctx HttpContext.Current;Htt…

supervisor守护进程配置

实际应用项目&#xff1a;http://github.crmeb.net/u/long 软硬件环境 centos7.6.1810 64bit cat /etc/redhat-release #查看系统版本 supervisor 3.4.0 python 2.7.5 supervisor简介 supervisor是一个用python语言编写的进程管理工具&#xff0c;它可以很方便的监听、启动…

Java compiler level does not match the version of the installed Java project facet.

问题原因&#xff1a; Facted Project 中的Java 版本设定与项目的Java编译器的compliance level设定不一致。 解决办法&#xff1a; 把两者设置成相同。 转载于:https://www.cnblogs.com/starxing/p/5751778.html

登录授权验证之OAuth2.0

实际应用项目&#xff1a;http://github.crmeb.net/u/long 本文将从几个方面了解和学习使用OAuth2.0。对不对就不管了&#xff0c;反正我也几乎不会用到。ps.有个项目用到了&#xff0c;所以才会有本文。 OAuth2.0介绍和功能微信开放平台和github的OAuth2.0接入应用自己写一个…

2010-2011 ACM-ICPC, NEERC, Moscow Subregional Contest Problem I. Interest Targeting 模拟题

Problem I. Interest Targeting题目连接&#xff1a; http://codeforces.com/gym/100714 Description A unique display advertisement system was developed at the department of advertising technologies, Yaagl Inc. The system displays advertisements that meet the in…

Linux 服务器必备的安全设置

这里给大家推荐一款免费迭代 二开便捷的商城项目&#xff1a;源码直通车>>> 好不容易买了服务器&#xff0c;如果因为自己的疏忽&#xff0c;被黑客黑掉的话&#xff0c;那真的是太糟糕了&#xff01; 下面告诉你一些简单的方法提高服务器的安全系数&#xff0c;我的…

面向对象重载

1.使用面向对象来求两个圆之间的面积2.函数重载函数重载需要的条件&#xff1a;函数名要相同&#xff0c;参数的个数或者参数的类型不同3.this关键字虽然写在类里面&#xff0c;但不是属于类的&#xff0c;而是属于该对象的一般来说在类里面 this关键字是可以省略的&#xff0c…

VMware创建Linux虚拟机并安装CentOS(一)

在VMware中新建虚拟机&#xff0c;在新建虚拟机向导中&#xff0c;选择“自定义&#xff08;高级&#xff09;”选项&#xff0c;鼠标单击“继续”按钮 选择VMware的版本workstation9.0(VMware版本对硬盘、内存、cpu等硬件的支持大小数量不同,选择不同版本可以看到差别&#xf…