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

来源:互联网 发布:安卓数据导入iphone6s 编辑:程序博客网 时间:2024/06/10 00:51

说完了父子组件的通信,是通过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











原创粉丝点击