Vue非父子组件通信

一、中央事件总线bus

在 Vue.js 2.x 中,推荐使用一个空的 Vue 实例作为中央事件总线(bus)。
示例代码如下:

<body>
		<div id="app">
			{{ message }}
			<component-a></component-a>
		</div>
		<template id="tmp">
			<button @click="handleEvent">传递事件</button>
		</template>
		<script type="text/javascript" src="../js/vue-2.4.0.js" ></script>
		<script>
			var bus = new Vue(); //定义一个空的vue实例bus
			Vue.component('component-a',{
				template: '#tmp',
				methods: {
					handleEvent:function () {
						bus.$emit('on-message','来自组件componet-a的内容'); //通过bus.$emit向父组件传参
					}
				}
			});
			var vm = new Vue({
				el: "#app",
				data: {
					message: ''
				},
				mounted:function () {
					var _this = this; //把 this 的实例(vm)赋给_this
					bus.$on('on-message',function (msg){ //通过$on来接受子组件的信息
						_this.message = msg; //这里如果继续使用this表示的是bus的实例
					});
				}
			})
		</script>

首先创建一个名为 bus 的空实例,然后全局定义一个组件,最后创建 Vue 实例 app,在 app初始化时,也就是在生命周期 mounted 钩子函数里监听了来自 bus 的事件 on-message,而在组件 component-a 中,点击按钮会通过 bus 把事件 on-message 发出去,此时 app 就会接收到来自 buss 的事件,进而在回调里完成自己的业务逻辑。

二、父链

在子组件中,使用 this.$ parent 可以直接访问该组件的父实例或组件,父组件也可以通过 this.$children 访问它所有的子组件,而且可以递归向上或向下无限访问,直到根实例或最内层的组件。示例代码如下:

<div id="app">
			<p v-text="message"></p>
			<component-a></component-a>
		</div>
		
		<template id="tmp">
			<button @click="handleEvent">通过父链直接修改数据</button>
		</template>
		<script type="text/javascript" src="../js/vue-2.4.0.js" ></script>
		<script>
			Vue.component('component-a',{
				template: '#tmp',
				methods: {
					handleEvent: function () {
						this.$parent.message = '来自组件component-a的内容';
					}
				}
			});
			var vm = new Vue({
				el: "#app",
				data: {
					message: ''
				}
			})
		</script>

尽管 Vue 允许这样操作,但在业务中,子组件应该尽可能地避免依赖父组件的数据,更不应该主动修改它的数据,因为这样使得父子组件紧耦合,只看父组件,很难理解父组件的状态。父组件最好还是通过 props 和 $emit 来通信。

三、子组件索引

当子组件较多时,通过 this.$children 来一一遍历出我们需要的一个组件实例是比较困难的,尤其是组件动态渲染时,它们的序列是不固定的。Vue 提供了子组件索引的方法,用特殊的属性 ref 来为子组件指定一个索引名称,示例代码如下:

<div id="app">
			<p v-text="message"></p>
			<component-a></component-a>
		</div>
		
		<template id="tmp">
			<button @click="handleEvent">通过父链直接修改数据</button>
		</template>
		<script type="text/javascript" src="../js/vue-2.4.0.js" ></script>
		<script>
			Vue.component('component-a',{
				template: '#tmp',
				methods: {
					handleEvent: function () {
						this.$parent.message = '来自组件component-a的内容';
					}
				}
			});
			var vm = new Vue({
				el: "#app",
				data: {
					message: ''
				}
			})
		</script>

在父组件模板中,子组件标签上使用 ref 指定一个名称,并在父组件内通过 this.$refs 来访问指定名称的子组件。 $refs只在组件渲染完成后才填充,并且它是非响应式。它仅仅作为一个直接访问子组件的应急方案,应当避免在模板或计算属性中使用 $refs。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值