当前位置: 首页 > Web前端 > vue.js

vue中的组件通信方式

时间:2023-03-31 18:28:39 vue.js

$attrs和$listeners当多级组件嵌套需要传递数据时,通常使用的方式是通过vuex。但是如果只是传递数据而不做中间处理的话,用vuex来处理就有点大材小用了。为此,Vue2.4版本提供了另一种方法----$attrs/$listeners$attrs:包含父作用域中prop无法识别(和获取)的属性绑定(class和style除外)。当一个组件没有声明任何props时,所有的父作用域绑定(class和style除外)都会被包含在这里,内部组件可以通过v-bind="$attrs"传递。通常与interitAttrs选项一起使用。$listeners:包含父作用域中的v-on事件监听器(没有.native装饰器)。它可以将v-on="$listeners"传递给内部组件;它是一个包含了所有作用于这个组件的监听器的对象,你可以配合v-on="$listeners"将所有的事件监听器指向这个组件的特定子元素。inheritAttrs:默认值为true,继承所有应用于子组件根元素的父组件属性(props的特定绑定除外)作为一个普通的HTML特性,如果你不想让组件的根元素继承该特性setinheritAttrs:false,但是类属性会被继承。主要目的是将数据从父组件传递给子组件或孙组件。"foo":boo="boo":coo="coo":doo="doo"title="前端公虾"@func1='Func1Click'@func2='Func2Click'\>

子组件孙子组件:曾孙组件:inheritAttrs默认情况下,父作用域中不被视为props的属性绑定将“回退”并作为普通HTML属性应用于子组件当组成一个包装目标元素或另一个组件的组件时,这可能并不总是按预期运行。通过将inheritAttrs设置为false,这些默认行为将被删除。这些特性可以通过实例属性$attrs生效,并且可以通过v-bind显式绑定到非根元素上。(注意:这个选项不影响class和style绑定)我们没有在子组件中做[inheritAttrs:false,//可以关闭自动挂载在组件根元素上的props中未声明的属性],现在看子组件在浏览器上的渲染:当我们添加这个属性时:总结:父组件传递两个参数boo`coofoodootitle`给子组件,但是子组件内部的`props`只接收一个参数`foo`,not接收`boocoodootitle,没有接收到的冗余属性将作为子组件根元素的属性节点。html`形式会显示为:
如上情况是因为inheritAttrs选项默认为true,但这和$attrs有什么关系呢?我们来解读一下官网最后几句话:通过设置inheritAttrs为false,这些默认行为就会被去掉。这些特性可以通过实例属性$attrs生效,并且可以通过v-bind显式绑定到非根元素上。也就是说,如果在子组件中将inheritAttras选项设置为false,我们可以通过$attrs属性获取组件props中没有定义但在父组件中传入的属性值:childcomponent:created(){console.log(this.$attrs);//{"boo":"Html","coo":"CSS","doo":"Vue","title":"前端工匠"}}$attrs只是说结合inheritAttrs获取$attrs属性,两者结合最强大的是实现了深层组件之间的值传递。

子组件1

foo:foo被绑定为props属性{{foo}}

子组件的$attrs:{{$attrs}}

孙子组件

嘘:{{boo}}

childCom2:{{$attrs}}

fuc1按钮fuc2button
注意两点:作为中间传递数据的组件,必须设置选项inheritAttrs将其设置为false以正确获取$attrs数据。在正常使用中,v-bind使用v-bind:src=xx或:src=xx的形式。这里使用v-bind=xx是指将一个包含键值对的对象绑定到一个组件上。上面的listener提到了使用$attrs实现数据的向下传递,但是如何实现下层数据或事件的向上交互呢?**这里我们要用到$listeners$listeners和$attrs表面上意思一样,attrs是向下传递数据,listeners是向下传递的方法,通过手动调用方法中的方法触发$listenersobject从父对象接收到的函数。父组件、子组件、孙组件对比:与$attrs的使用类似,中间组件不使用父组件传过来的事件,同样作为过渡。使用v-on='this.$listeners'会接受来自父级传入的事件,再次向下传递,直到传递给末级组件,末级组件可以使用this.$listeners来调用父级事件,从而改变子组件上父级绑定的属性值。Provide/inject很简单:父组件通过provide提供数据;子组件通过inject读取数据注意:这里不管子组件嵌套多深,只要调用了inject,provide中的数据就可以注入,并且不限于从当前父组件的props属性返回数据//A.vue//B.vue//C.vue一言以蔽之:通过provider在祖先组件中提供变量,然后通过inject在后代组件中注入变量provide/injectAPI主要解决跨级组件之间的通信问题,但其使用场景主要是子组件获取上层组件的状态,跨层组件之间建立主动提供和依赖注入的关系。注意:这里无论子组件嵌套多深,只要调用了inject,就可以注入provide中的数据,不限于从当前父组件的props属性中返回数据。ref/refsref:如果在正常的DOM元素上使用时,引用指向DOM元素;如果**用在子组件上,引用指向组件实例**,可以直接调用组件的方法或通过实例访问数据。我们来看一个访问组件的例子,ref://childcomponentA.vueexportdefault{data(){return{name:'Vue.js'}},methods:{sayHello(){console.log('hello')}}}//父组件app.vue$children/$parent////childIn组件注意边界条件,比如在#app上带$parent得到一个newVue()的实例,在这个实例上带$parent得到undefined,在底部子组件中带$children是一个空数组。parent和$children的值是不同的,$children的值是一个数组,$parent是一个对象总结:以上两种方法用于父子组件之间的通信,比较常用的是用于父子组件通信的道具;也不能用于非父子组件之间的通信。总结常见的使用场景可以分为三类:父子组件通信:props;$父母/$孩子;提供/注入;参考;$attrs/$listeners兄弟组件通信:eventBus;vuex跨层通信:eventBus;浏览器;提供/注入、$attrs/$listeners