Vue实践之--非父子组件通信

说完了父子组件的通信,是通过props和$emit来实现的,那么非父子组件之间的通信又如何呢?有以下3种方式:bus总线,父链和子组件的索引;

bus总线

HTML部分:

<div id="container" v-cloak>
		<p>{{message}}</p>
		<!-- bus总线 -->
		<my-component @hehe="alerMSg"></my-component>
	</div>
javascript部分:

var bus = new Vue();//bus(中央事件总线)
		//组件
		Vue.component("my-component",{
			template:"<button @click='setMessage'>点我</button>",
			data:function(){
				return {
					msg:"今天,我们来看下非父子组件怎么通信"
				}
			},
			methods:{
				setMessage:function(){
					bus.$emit("on-msg",this.msg);//由bus将该事件on-msg传递出去
					this.$emit("hehe",this.msg)//父组件自定义事件
				}
			}
		})
		var myApp = new Vue({
			el:"#container",
			data:{
				message:"hello,world!"
			},
			mounted:function(){
				var _this  = this;
				// 在实例初始化的时候,监听该事件
				bus.$on("on-msg",function(ele){//回调函数
					_this.message = ele
				})
			},
			methods:{
				alerMSg:function(ele){
					alert(ele)
				}
			}
		})//实例
在上述例子中,首先由一个 空的Vue实例作为中央事件总线bus,当子组件的点击事件触发的时候,通过bus.$emit("actionName",[参数1],[参数2]...)将事件名‘actionName’的事件传了出去,因为在Vue实例myApp的 钩子函数mounted监听着来自bus的事件actionName,所以实例app就会接收到来自bus的事件, 进而在回调函数里执行自己的业务逻辑代码;
可见,无论是将"事件"传出去,还是监听传递过来的事件都离不开bus,所以bus就像是一个生活中的中介一样, 可以将以上的过程想象成一个对话:
当子组件的事件发生时告诉bus--赶紧把事件"on-msg"放了吧!bus听到后就通过bus.$emit将放了,然后Vue实例通过mounted侦听到这个消息后,就还是让bus把绑定在该事件下,该做的事情给做了就行了(执行回调函数)。

父链

HTML部分:

<div id="subContainer">
		<p>{{notes}}</p>
		<your-component></your-component>
	</div>
javascript部分:

Vue.component("your-component",{
			template:"<p @click='changeStr'>子组件</p>",
			data:function(){
				return {
					NOTS:"实例中的数据也会被改变呢!"
				}
			},
			methods:{
				changeStr:function(){
					this.$parent.notes = this.NOTS
				}
			}
		})
		var yourApp = new Vue({
			el:"#subContainer",
			data:{
				notes:"我是实例中的数据"
			}
		})
所谓的父组件/子组件都是相对的,一个组件可能既是父组件也是子组件,就看相对于什么了--比如说:自定义组件当嵌套在一个实例中时是作为该实例的子组件的,而自定义组件本身又是template的父组件。
在子组件中可以通过this.$parent来直接访问该组件的父实例(或组件), 也就是说可以通过this.$parent来直接操纵父实例(或组件)中的数据,因为在子组件中this就代表组件本身,this.$parent就是“组件的父亲”--实例或者组件。
但是这样做并不好,
因为你直接改变了父组件中的数据,这样就会导致父子组件的紧耦合?为什么呢,因为父组件中的数据是“源数据”,一旦改变了父组件中的数据,就会达到牵一发而动全身的后果(所有跟该数据相关的计算属性,判断等等都将受到影响), 所以父子组件的通信还是要靠props和$emit来实现比较好。
反之父实例也可以通过this.$children来访问该父实例下的所有子组件(不推荐);

子组件索引

HTML部分:

<div id="subsubContainer">
		<p>{{subnotes}}</p>
		<he-component ref = "hihi"></he-component>
		<!--由"我是子组件中的数据"变成"我是实例中的数据,哈哈!" -->
		<he-component ref = "lele"></he-component>
		<!--由"我是子组件中的数据"变成"我是实例中的数据,哈哈!" -->
		<he-component ref = "lala"></he-component>
		<button @click="setSonCompoData">点我看效果</button>
	</div>
javascript部分:

Vue.component("he-component",{
			template:"<p>{{SUBNOTS}}</p>",
			data:function(){
				return {
					SUBNOTS:"我是子组件中的数据"
				}
			}
		})
		var hisApp = new Vue({
			el:"#subsubContainer",
			data:{
				subnotes:"我是实例中的数据,哈哈!"
			},
			methods:{
				setSonCompoData:function(){
					this.$refs.lele.SUBNOTS = this.subnotes;//
					this.$refs.hihi.SUBNOTS = this.subnotes;
					//第一,第二个子组件中的数据SUBNOTS变成了“我是实例中的数据,哈哈!”
				}
			}
		})
一个父实例中可能嵌套有多个子组件,那么该如何快速的找到目标子组件呢?

就是通过在父实例(组件)中的子组件标签上使用ref属性指定一个名称,并在父实例(组件中)通过this.$refs.名称来访问对应的子组件(里面的数据更不在话下了),不过其仅仅是作为一种访问子组件的应急方案,尽量不要在模板template或者计算属性中使用$refs











  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值