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

Vue中常见的组件间通信方案及典型应用场景

时间:2023-03-14 11:14:16 科技观察

什么是组件通信所谓组件通信就是组件之间的数据交互,即一个组件A中的数据传递给另一个组件B,并且可以makeComponentB根据这些数据更新接口。在Vue中,有许多可用的通信方案。下面介绍几种常见的组件通信方案及其典型应用场景。1.父子组件通信场景父子组件通信是最典型的组件通信场景,没有之一,它们之间的通信主要使用自定义属性或者ref。首先是自定义属性,应用广泛。使用子组件中的props选项接收,子组件返回数据给父组件,使用自定义事件,使用子组件中的$emit()方法触发执行,并将数据返回给父组件。//定义组件h1-boxVue.component("h1-box",{//通过props设置自定义属性title接收组件的外部值props:["title"],//设置自定义事件通过emits事件向外发送Eventemits:['give'],methods:{clickHandler(){//通过$emit()方法触发执行,带出当前组件数据this.$emit('give',{name:'lucy'})}},mounted(){//通过this.title可以获取外部传入组件的值console.log(this.title);},});第二种是使用ref来实现通信。我们知道使用ref可以快速访问一个组件实例对象及其内部数据和方法。在这种情况下,借助父组件中的refs调用子组件中的方法,并将事件参数传递给子组件。当然需要注意的是,在Vue开发中,要尽量减少ref的使用。

newVue({el:"#app",mounted(){//get对组件实例,可以操作组件实例console.log(this.$refs.son);letvm2=this.$refs.son;//修改子组件的响应数据msgvm2.msg="sz2111";//调用子组件的changeMsg方法vm2.changeMsg("sz2116");},components:{//定义子组件son:{data(){return{msg:"sz2114",};},方法:{changeMsg(val){this.msg=val;},},模板:`

helloworld

`,},},});2.兄弟组件通信场景该场景使用状态提升,这个概念来源于React中状态提升的思想。所谓statepromotion就是当两个组件要共享一段数据时,我们可以找到这两个组件最近的父组件,在最近的父组件中定义要共享的变量,然后通过props向下传递到子组件。需要注意的是,状态提升适用于应用程序在简单的兄弟组件之间进行通信。当遇到更复杂的组件关系时,使用状态提升就变得麻烦了。上图中,如果要点击Font按钮改变主题的字体大小,即Title和Font组件的字体大小都会改变。如果Title和Font组件都维护自己的组件状态数据,就不容易传递数据,那么可以将它们的状态存储在公共的父组件状态中,即状态提升。
//父组件newVue({el:'#app',data:{//将子组件需要的数据存放在公共父级fontSizeonthecomponent:12}})//子组件Vue.component('font',{//接受父组件通过自定义属性传入的值props:['font'],template:`hello
`})//子组件Vue.component('title',{//接受父组件通过自定义属性传入的值props:['font'],template:`world
`})3.根组件与后代组件通信场景该场景主要是provide/inject。使用provide选项,你可以在任何组件中注入数据;使用inject选项,您可以在后代组件中接受父组件注入的数据。需要注意的是,provide/inject的通信方案是非响应式的,即当父组件注入的数据发生变化时,后代组件不会自动更新上图中祖先组件通过provide传入的数据,在所有后代中的所有组件都可以通过inject获得。以下是通过provide/inject传递值的示例://rootcomponentnewVue({el:"#app",//provide它用于将数据传递给vue实例中的后续后代实例provide:function(){return{a:100,c:300,d:this.obj,};}});//定义组件oneVue.component("one",{//inject用于接收祖先通过provide传入的变量c,在后代组件中inject:["a"],template:`

我是一个组件---{{a}}

`,});//定义组件二,其中包含子组件一Vue.component("two",{//inject用于通过提供变量c接收后代组件中的祖先,并重命名为myCinject:{myC:"c",},template:`

我是两个组件---{{myC}}

`,});//定义组件三,其中包含子组件二Vue.component("three",{//inject用于在后代组件中接收祖先通过provide传入的变量b,并重复命名为bbb,并设置默认值为299999inject:{bbb:{from:"b",default:299999,},},template:`我是三元组---{{bbb}}`,});4.在slot通信场景封装组件时,可以为组件添加自定义属性使用该组件时,在父组件中使用#slotName='scope'指令接收子组件的slot传过来的数据。ElementUI中的Table表单和VantUI中的Tabbar组件都是使用槽通信的。

sz2114

sz2115

sz2116

sz2014

sz2015

sz2016

//全局组件Vue.component("child",{template:`

helloworld

`,});让vm=newVue({el:"#app",});5.没有直接关系的组件通信场景事件总线可以用于没有直接关系的组件之间的通信。事件总线是一种基于订阅-发布模式设计的通信方案。在任意组件中订阅指定的“频道”后,就可以在“频道”上接收消息。事件总线的强大之处在于它是一种“一对多”的通信方案或者是“多通道”的通信方案,非常强大。给老师发消息//中央eventbus:类似于一个事件对象//就像一个电信局varbus=newVue();//每个人都需要一个号码(事件名称)来接收短信//如果你想接收短信,你必须先去电信办卡--注册号码bus.$on("cyrevent",function(data){console.log("短信内容是");console.log(data);});newVue({el:"#app",data(){return{duanxin1:"",};},methods:{clickHandler(){//有人要给我发消息bus.$emit("cyrevent",this.duanxin1);},},});6.大型项目中复杂的组件通信场景——Vuex状态管理Vuex状态管理是一种状态管理工具,可以实现任意组件之间的数据通信。Vuex提供了state和mutations等接口,可以轻松实现任何未知关系的组件之间的数据交互。因此,我们常称Vuex为Vue开发中的终极通信解决方案。最终的意义不是它可以随意替代其他通信方案,而是Vuex简单易用,可以清晰地管理数据流。上图是vuex官网的workflow流程图,很形象。7、其他的一些组件通信方案上面说的是比较常用的组件通信方式,还有一些方式是上面的通信方式无法使用的替代方案。第一个是:$parent/$children。通过这两个API,你可以在组件树之间自由穿梭。在当前组件的范围内,我们可以访问任何其他组件的内部数据并调用它的方法。因此,这也是一种可用的通信方案。第二个是:$attrs/$listeners。使用$attrs访问父组件传递的自定义属性(class和style除外),使用$listeners访问调用父组件传递的自定义事件,调用自定义事件向父组件返回数据。这两个内置的API在某种程度上可以看作是父子组件通信的替代方案。总结虽然Vue中有很多可用的通信方案,但要注意“不要滥用”。在同一个项目中,选择适合场景的通信方案非常重要。不要使用太多的通信方式,这样会使代码难以维护。一个数据流不清晰的Web应用通常很难实现可持续发展。作者:陆荣涛链接:https://juejin.cn/post/7138709654464364581来源:稀土掘金版权归作者所有。商业转载请联系作者授权,非商业转载请注明出处。