当前位置: 首页 > 科技观察

8种vue组件通信方式详解

时间:2023-03-13 17:18:54 科技观察

对于vue来说,组件是很常见的,很多平台都封装了自己的一套组件,比如elementui,weui等。同时,消息的传递组件之间也很重要。下面是我总结的组件间消息传递的各种方式。一共有8种方式。有不足之处可以留言补充,互相学习。1.props和$emit这是最常见的父子组件通信方式。父组件通过props向子组件传输数据,子组件通过$emit触发事件向父组件传输数据。示例:父组件Vue.component('parent',{template:`

父组件

`,data(){return{message:'Hellowebshow'}},methods:{//执行子组件触发的事件getChildData(val){console.log(val)}}})varapp=newVue({el:'#app',template:`
`})subcomponentVue.component('child',{//获取传入的数据props父组件:['message'],data(){return{myMessage:this.message}},template:`
`,methods:{passData(val){//触发父组件中的事件this.$emit('getChildData',val)}}})解析:父组件将消息数据传给子组件,并通过v-on绑定getChildData事件,监听子组件的触发事件;子组件通过props获取相关消息数据,最终通过this.$emit触发getChildData事件。2.$attrs和$listeners第一种方法处理父子组件之间的数据传输有问题:如果有多层嵌套,父组件A下有子组件B,组件B下有组件C.如果A要传递数据给组件C怎么办?如果使用第一种方式,我们必须让组件A通过prop将消息传递给组件B,组件B通过prop将消息传递给组件C;如果组件A和组件C之间还有很多组件的话,采用这种方法就很复杂了。从Vue2.4开始,提供了$attrs和$listeners来解决这个问题,允许组件A向组件C传递消息。C组件Vue.component('C',{template:`
`,methods:{passCData(val){//触发父组件A中的事件this.$emit('getCData',val)}}})B组件Vue.component('B',{data(){return{myMessage:this.message}},模板:`
`,//获取父组件传过来的数据props:['message'],methods:{passData(val){//触发父组件中的事件componentthis.$emit('getChildData',val)}}})一个组件Vue.component('A',{template:`

thisisparentcomponent!

`,data(){return{message:'你好',messageC:'Helloc'}},methods:{getChildData(val){console.log('这是来自B组data')},//执行C子组件触发的事件getCData(val){console.log("ThisisthedatafromtheCcomponent:"+val)}}})varapp=newVue({el:'#app',template:`
`})分析:之所以能在C组件中直接触发getCData,是因为B组件在调用C组件时,使用v-on绑定$listeners属性通过v-bind绑定$attrs属性,C组件可以直接获取A组件传下来的props(B组件声明的props除外)3.v-model父组件通过v-model传值给子组件,它会自动传递一个valueprop属性,并通过this.$emit('input',val)中的this.$emit('input',val)自动修改v-model绑定的值子组件。子组件Vue.component('child',{props:{//v-model会自动传递一个prop属性,字段为value:String,},data(){return{myMessage:this.value}},methods:{changeValue(){//可以通过这样调用来改变父组件上v-model绑定的值this.$emit('input',this.myMessage);}},template:`
`})父组件Vue.component('parent',{template:`

thisisparentcomponent!

{{message}}

`,data(){return{message:'Hello'}}})varapp=newVue({el:'#app',template:`
`})4.provide和inject变量在父组件中通过provider提供,然后在子组件中通过provider注入变量inject不管子组件有多深,只要调用了inject,就可以注入provider中的数据。而不是局限于只能从当前父组件的prop属性中获取数据,只要在父组件的生命周期内,子组件就可以调用。子组件Vue.component('child',{inject:['for'],//获取父组件传过来的数据data(){return{myMessage:this.for}},template:`
`})父组件Vue.component('parent',{template:`

thisisparentcomponent!

`,provide:{for:'test'},data(){return{message:'Hello'}}})varapp=newVue({el:'#app',template:`
`})5.centraleventbus的上述方法是处理父子组件之间的数据传递,那么如果两个组件不是父子关系怎么办?也就是说,兄弟组件如何通信?在这种情况下,可以使用中央事件总线方法。新建一个Vue事件总线对象,然后通过bus.$emit触发事件,通过bus.$on监听触发的事件。Vue.component('brother1',{data(){return{myMessage:'Hellobrother1'}},template:`

thisisbrother1component!

`,methods:{passData(val){//触发全局事件globalEventbus.$emit('globalEvent',val)}}})Vue.component('brother2',{template:`

thisisbrother2compoent!

brother1传过来的数据:{{brothermessage}}

`,data(){return{myMessage:'Hellobrother2',brothermessage:''}},mounted(){//绑定全局事件globalEventbus.$on('globalEvent',(val)=>{this.brothermessage=val;})}})//中环事件总线varbus=newVue();varapp=newVue({el:'#app',template:`
`})6.parentandchildrenVue.component('child',{props:{value:String,//v-model会自动传递一个字段为value的prop属性},data(){return{mymessage:this.value}},methods:{changeValue(){this.$parent.message=this.mymessage;//这个调用可以改变父组件的值}},template:`
})视。component('parent',{template:`

thisisparentcomponent!

test
`,方法:{changeChildValue(){this.$children[0].mymessage='hello';}//这里推荐一个前端全栈开发交流圈:619586920突破技术瓶颈,提升思维能力},data(){return{message:'hello'}}})varapp=newVue({el:'#app',template:`
`})7.boradcast和dispatchvue1.0中提供了这个方法,vue2.0中没有,但是很多开源软件自己封装了这个方法,比如minui、elementui和iview等。比如下面的代码一般作为mixins使用,broadcast是给特定的父组件,触发事件,dispatch是给特定的子组件触发事件。该方法本质上还是对on、on、emit的封装,但是在一些基础组件中非常实用。functionbroadcast(componentName,eventName,params){this.$children.forEach(child=>{varname=child.$options.componentName;if(name===componentName){child.$emit.apply(child,[eventName].concat(params));}else{broadcast.apply(child,[componentName,eventName].concat(params));}});}exportdefault{methods:{dispatch(componentName,eventName,params){varparent=this.$parent;varname=parent.$options.componentName;while(parent&&(!name||name!==componentName)){parentparent.$parent;if(parent){name=parent.$options.componentName;}}if(parent){parent.$emit.apply(parent,[eventName].concat(params));}},broadcast(componentName,eventName,params){broadcast.call(this,componentName,eventName,params);}}};8。Vuex处理组件之间的数据交互。如果业务逻辑复杂,很多组件需要同时处理一些公共数据。这时,上述方法可能不利于项目维护。Vuex的做法就是把这些公共数据抽取出来,然后其他组件就可以读写这个公共数据,从而达到解耦的目的。