Vue--组件通信

组件通信

​ 组件间的数据共享

组件的关系:父子关系非父子关系

三种通信方式:

​ 1.父子通信:父组件的数据要传递给子组件

​ 2.子父通信:子组件的数据要传递给父组件

​ 3.非父子组件通信:非父子之间的数据传递

父向子传递数据

​ 1.在父组件中通过v-bind传递数据

		格式:<子组件 :自定义接收名称="要传递的数据"></子组件>

​ 2.在子组件中通过props属性来接收数据

		props:['自定义接收名称']

​ 3.在子组件中就可以通过 自定义数据名称来使用 数据了

HTML :

<div id="app">
    <father></father>
</div>

<!-- 父组件的模板内容 -->
<template id="father">
    <div>
        <p>父组件数据为:{{msg}}</p>
        <!-- message不是固定的,而是我们自定义的属性 -->
        <son :message="msg"></son>
    </div>
</template>

<!-- 子组件的模板内容 -->
<template id="son">
    <div>
        <p>子组件获取父组件的数据:{{message}}</p>
    </div>
</template>

JS :

Vue.compinent("father",{
    //找到id为father的template标签
    template:'#father',
    data(){
        return{
            msg:"I am is your father"
        }
    },
    //局部自定义的方式,去定义子组件
    components:{
        //定义子组件
        son:{
            template:'#son',
            //props中的元素必须与上面自定义的属性名一致,Prop是你可以在组件上注册的一些自定义attribute 属性
            props:['message']
        }
    }
})

new Vue({
    el:"#app",
})

props验证

​ props还可以对传入的参数进行验证,比如: 验证传入的是不是布尔值,是不是数组等

验证格式:

props:{
    数据1:{
        type:类型,
        default:默认值
    },
    数据2:{
        type:类型,
        default:默认值
    }
}
<div id="app">
    <navbar :title="title"></navbar>
</div>

<template id="navbar">
    <div>
        <button v-if="leftbutton">返回</button>
        <span>{{title}}</span>
        <button>搜索</button>
    </div>
</template>
Vue.component('navbar',{
    template:"#navbar",
    props:{
        title:{
            type:String,
            default:"标题"
        },
        leftbutton:{
            type:Boolean,
            default:false
        }
    }
})

new Vue({
    el:"#app",
    data:{
        title:"电影",
        leftbutton:false
    }
})

运行效果展示:返回按钮并未被创建

image-20220111193937028

单向数据流

​ 所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。

看案例:

<div id="app">
    <father></father>
</div>

<!-- 父组件的内容 -->
<template id="father">
    <div>
        <input type="text" v-model="msg">
        <p>父组件的数据为:{{msg}}</p>
        <hr>
        <son :message="msg"></son>
    </div>
</template>

<!-- 子组件的模板内容 -->
<template id="son">
    <div>
        <p>子组件获取父组件的数据:{{message}}</p>
        <input type="text" v-model="msg">
        <p>子组件获取父组件的数据为:{{msg}}</p>
    </div>
</template>
//定义一个全局的父组件
Vue.component('father',{
    //找到id为father的template标签
    template:"#father",
    data(){
        return{
            msg:"I am is your father"
        }
    },
    components:{
        //定义子组件
        son:{
            template:"#son",
            props:['message'],
            data(){
                return{
                    //初始化msg变量,它的值为父组件传递过来的数据
                    msg:this.message
                }
            },
            watch:{
                message(value){
                    this.msg = value
                }
            }
        }
    }
})

new Vue({
    el:"#app",
    data:{}
})

运行效果展示:

image-20220111200651838

​ 在子组件的输入框中输入新的值,其下也会相应的更新,而父组件则不会更新,在父组件输入新的值,子组件也会进行相应的更新

​ 【注意】不要在子组件中直接修改父组件传入的数据

子向父传递数据

​ 本质上是让子组件调用父组件的方法,通过方法传参的方式传递数据

1.在父组件使用子组件的时候,给子组件绑定一个自定义的事件名称,值为 自己的方法

<子组件 @自定义事件名 = "事件处理函数" />

2.在子组件自定义一个方法,在方法中 通过 this.$emit("自定义事件名",params)来触发传递过来的方法,并通过参数的方式传递数据

<div id="app">
    <father></father>
</div>

<!-- 父组件的模板内容 -->
<template id="father">
    <div>
        <p>儿子发消息来了:{{msg}}</p>
        <hr>
        <son @change="getMsg"></son>
    </div>
</template>


<!-- 子组件的模板内容 -->
<template id="son">
    <div>
        <button @click="sendMsg">给父组件发消息</button>
    </div>
</template>
//定义一个全局的父组件
Vue.component('father',{
    template:"#father",
    data(){
        return{
            msg:'',
        }
    },
    methods:{
        getMsg(value){
            this.msg = value
        }
    },
    //局部组件定义的方式,去定义子组件
    components:{
        //定义子组件
        son:{
            template:"#son",
            data(){
                return{
                    msg:"没钱吃饭了"
                }
            },
            methods:{
                sendMsg(){
                    this.$emit('charge',this.msg)
                }
            }
        }
    }
})

new Vue({
    el:"#app",
    data:{}
})

点击发送消息运行效果展示:

image-20220111202753588

非父子通信

非父子组件要实现通信,有两个解决方案:

​ 1.bus 中央事件总线

​ 2.vuex 状态管理

bus中央事件总线:使用一个空的Vue实例作为中央事件总线,通俗理解:中介

步骤

1.创建一个空的Vue实例
	let bus = new Vue();

2.在组件的mouted钩子函数中,通过bus.$on来监听一个自定义类型的事件函数,
	methods(){
        bus.$on("自定义事件名",(传递的数据)=>{
            //...
        })
    }

3.在另外一个组件的方法中,通过bus.$emit来触发这个自定义类型的事件函数
	bus.$emit("自定义事件名",传递的数据)
一、$emit
1this $emit('自定义时间名',要传递的数据)
2、触发当前实例上的时间,要传递的数据会传递给监听器

二、$on
1VM.$on("事件名",callback)---------callback回调$emit要传送的数据
2、监听当前实例上自定义时间

实例:

<div id="#app">
    
</div>

<!-- 租客组件模板内容 -->
<template id="tenant">
    <div>
        <h3>租客</h3>
        <p>租客信息:{{msg}}</p>
        <p>接收到的房东信息:{{renterMsg}}</p>
        <!-- 点击按钮,将租客信息发送给房东 -->
        <button @click="rentIn">我要租房</button>
    </div>
</template>

<!-- 房东组件模板内容 -->
<template id="renter">
    <div>
        <h3>房东</h3>
        <p>房东信息:{{msg}}</p>
        <p>接收到的租客信息:{{tenantMsg}}</p>
        <!-- 点击按钮,将房东信息发送给租客 -->
        <button @click="rentOut">我要租房</button>
    </div>
</template>
let bus = new Vue();

new Vue({
    el:"#app",
    data:{
        
    },
    components:{
        //租客组件
        tenant:{
            template:"#tenant",
            data(){
                return{
                    msg:"无不良嗜好,单身",
                    reterMsg:""
                }
            },
            methods:{
                rentIn(){
                    bus.$emit("renter-event",this.msg)
                }
            },
            //创建阶段的第4个钩子函数
            mounted(){
                //监听自定义事件
                bus.$on("tenant-event",value => {
                    this.renterMsg = value;
                })
            }
        },
        
        //房东组件
        renter: {
            template: "#renter",
            data() {
                return {
                    msg: "押一付三,押金不退",
                    tenantMsg: ""
                }
            },
            methods: {
                rentOut() {
                    bus.$emit("tenant-event", this.msg)
                }
            },
            //创建阶段的第4个钩子函数
            mounted() {
                //监听自定义事件
                bus.$on("renter-event", value => {
                    this.tenantMsg = value;
                })
            }
        }
    }
})

运行效果展示:

image-20220112211232405

点击我要租房按钮,房东将会接收到租客的信息,点击我要招租,租客将会接收到房东的信息

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值