vue组件的通信方式

目录

        一、props与$emit

        二、ref/$ref

        三、eventBus

        四、provide与inject

        五、$children与$parent

        六、$attrs / $listeners


        前言 : 组件作为vue最强大的功能之一,但每个组件实例模块却是彼此独立的,这就意味着他们之间无法直接的进行引用,这时候,它们之间的通讯就变得十分重要了。

 一、props与$emit       

        props是子组件中的一个属性,可以是数组也可以是对象,是对象时会对接收数据进行判断操作。其只能用于接收父组件中传入的数据,如果想向父组件中传递数据,需要使用$emit方式并向里面加入对应参数,父组件使用v-on方式进行相互绑定即可。


父组件的传入数据方式与接收子组件传回数据方式

其中 :parHandData 为自定义的名字,子组件的props与其对应即可,list为data中定义好的数据

使用v-on绑定子组件$emit写入的自定义事件

// 父组件中
<template>
    <div id="app">
        // 使用子组件
        <son-module :parHandData="list" v-on:binding="dinMetcik"></son-module>  // 将数据传递给子组件
    </div>
</template>
<script>
    // 引入子组件
    import sonModule from ./sonModule.vue
    export default {
        name: "father",
        components: sonModule // 注册子组件
		data() {
			return {
                list: [
					    {id:1,name:"imac",price:1},
						{id:2,name:"ipad",price:2},
					    {id:3,name:"iphone",price:3}
				]
            }
		},
        methods: {
            // 通过绑定触发的一个事件,接收到的参数为子组件中$emit传入的两个参数
            dinMetcik(sonParamaO,sonParamaT){
                sonParamaO.price = sonParamaT;
            }
        }
    }
</script>

子组件的接收

注意:接收的数据外面需要嵌套引号,如需使用,直接this.:parHandData即可

如需传回父组件,使用$emit内写入相应参数        

// 子组件中
export default {
    name: son,
    props: ["parHondData"], // 接收到父组件传递的数据
    mounted(){
        console.log(this.parHondData); // 挂载后显示一下
        // 传入父组件的参数,第一个为自定义事件,后两个为参数
        this.$emit("binding",this.parHondData[2],this.parHondData[2].price+1);
    }
};

当然,子传父的$emit方法有3种传递方式,还有syan指令配合updata绑定和model属性操作方式。props作为最传统的通信方式,正常父子通信轻松实现,其实很多场景下的通信也都能够实现,但是可能要有很多个props与$emit来回嵌套,所有有必要出现更方便多样的通信方式。


二、ref/$ref方式

父组件中对子组件数据进行操作

ref使用在子组件中,相当于为父组件中使用注册的子组件绑定一个标识,标识到的子组件会存在与父组件中的this.$ref,这里面包含了标识过的子组件的基本所有信息 。

// 父标签中
<template>
    <son ref="child"></son>
</template>
<script>
    export default {
        name: "father",
        data() {
			return {
               hondChild: "传入子元素的数据"
            }
		},
        mounted(){
            console.log(this.$ref.child); // 打印的为整个子组件中的内容
            // 如果需要对子组件中的值进行改变,可直接在父组件中进行操作
            this.$ref.child.hondPar = this.hondChild;
        }
		
    }
</script>

子组件中

在子组件中查找父组件,只需其使用this.$parent即可查到父组件中的所有内容

this.$parent,顾名思义,就是当前组件父亲,即父组件。如果查找爷爷的话,则是this.$parent.$parent

如果想要传递,则可以效仿上面父组件中操作子组件的方式

<script>
	export default {
		name: "son",
        data(){
            return {
                hodePar: ""
            }
        },
        mounted(){
            // 在父组件中已找到子组件内容并将其修改
            console.log(this.hodePar); // 传入子元素的数据
        }
	};
</script>

三、eventBus

eventBus事件总线适用于父子组件、非父子组件等之间的通信。

使用eventBus方式的话,则需要在外部建立一个js文件,里面注入相应代码后,即可作为组件的事件管理中心,类似于代理人。

注入代码如下:

// 因为需要使用vue,所以引入vue
import Vue from "vue"
// 创建一个相互传递中间的代理人
export const EventBus = new Vue();

在事件管理中心创建好后,要进行传递数据的组件需要在内部引入以上创建的js代码进行使用

以下假设有两个需要传递数据的兄弟组件BrotherGe和BrotherDi

弟弟向哥哥传递方式如下

<script>
	// 需要属于代理人进行传递,所以需要引入代理人
	import {EventBus} from './EventBus.js'	
	export default{
		name: "BrotherDi",
		data(){
			return {
				Di_date: "传给哥哥的数据"
			}
		},
		mounted(){
			// 自定义一个标识并写入要传递的数据发送给哥哥
			EventBus.$emit("assd",{val:this.Di_date});
		}
	}
</script>

哥哥接收的方式如下

<script>
	import {EventBus} from '../EventBus.js'	
	export default{
		name: "BrotherGe",
		data(){
			return {
				Ge_date: ""
			}
		},
		mounted(){
			// 哥哥使用$on监听到弟弟发送到的,并使用内部数据进行接收
			EventBus.$on("assd",({v}) => {this.Ge_date = v});
            console.log(this.Ge_date); // 传给哥哥的数据
		}
		
	}
</script>

、provide/inject

注入/依赖(provide/inject)通信方法,用于处理父子组件、爷孙组件、亦或者隔代许多的组件都相对方便,层数再深也好处理,一步解决,不用一层一层去传递数据了。且相互传递的两个组件是相互绑定的,也就是说,在子组件中改变其数据时也会影响父组件的。

provide与inject是vue提供的两个钩子,和data、methods等同级,其中provide与data写法相似,都是一个函数,通过return返回出要传递的数据。而inject类似于props,可以是数组也可以是对象,能接收到provide传入的数据。

provide传递方式如下

<script>
	export default{
		name: "parProvide",
		data(){
			return {
				proCs: "provide传给子代的"
			}
		},
        provide(){
			return {
				proCs: this.proCs // 参数名为自定义,参数值为当前组件里的内容
			}
		}
	}
</script>

inject接收方式如下

<script>
	export default {
		name: "sonInject",
		// 接收父组件通过Provide属性传入的数据
		inject: ["proCs"], // 如果修改proCs的数据,父组件也会相应改变的
		mounted(){
            console.log(this.proCs); // provide传给子代的
        }
	}
</script>

 五、$children与$parent

听其名,闻其意。$children可以在父组件中直接访问到子组件的实例,而$parent可以在子组件中访问到父组件的实例,基本包含到了所有信息。这里需要注意以下,因为父组件会有多个子组件,而子组件只能有一个父组件,所以当在父组件中使用this.$children时访问到的会是一个数组,这个数组中包含着所有的子组件,即this.$children[index]来访问用到的子组件。相反,子组件访问父组件则不需要。

这种方式可以直接访问到数据,不需要刻意的代码去传递参数。

父组件中访问子组件

<script>
	import children from './children.vue'	
	export default{
		name: "father",
        conponents: {
            children
        }
		data(){
			return {
				fatherTest: "父组件中的内容"
			}
		},
        mounted(){
            // 访问到子组件中的内容
            console.log(this.$children[0]); // 子组件中的内容
        {
		
	}
</script>

子组件中访问父组件

<script>
	import children from './children.vue'	
	export default{
		name: "children",
        conponents: {
            children
        }
		data(){
			return {
				sonTest: "子组件中的内容"
			}
		},
        mounted(){
            // 访问到父组件中的内容
            console.log(this.$parent.fatherTest); // 父组件中的内容
        {
		
	}
</script>

六、$attrs / $listeners

如果是用props/ $emit 来一级一级的传递,确实可以完成,但是比较复杂;如果使用事件总线,在多人开发或者项目较大的时候,维护起来很麻烦;如果使用vuex,如果仅仅是传递数据,那可能有点浪费了。

针对上述情况,vue引入了 $attrs / $listeners,实组件之间的跨代通信。

$attrs:继承所有的父组件属性(除了props传递的属性、class 和 style),一般用在子组件的子元素上 $listeners:该属性是一个对象,里面包含了作用在这个组件上的所有监听器,可以配合 v-on=" $listeners " 将所有的事件监听器指向这个组件的某个特定的子元素。(相当于子组件继承父组件的事件) 再说一下 inheritAttrs

默认值为true,继承所有的父组件属性除props之外的所有属性。 只继承class属性。 $attrs / $listeners的用法: A组件(APP.vue):

B组件(Child1.vue):

C 组件 (Child2.vue):

在上述代码中:

C组件中能直接触发test的原因在于 B组件调用C组件时 使用 v-on 绑定了$listeners 属性 在B组件中通过v-bind 绑定$attrs属性,C组件可以直接获取到A组件中传递下来的props(除了B组件中props声明的) 总结 根据以上对这6种组件间的通信方法,可以将不同组件间的通信分为3种类型:父子组件间通信、兄弟组件间通信、任意组件间通信

希望能够有所帮助!

猜你喜欢

转载自blog.csdn.net/weixin_60678263/article/details/126737844