前言
提示:Vue中 常见的组件通信方式可分为三类:
- 父子通信
通常父子传值都是 通过prpos,子组件通过events接收
通过父链/子链 通信($parent/$chldren);
ref也可以访问实例
provide/inject
$attrs/$listeners
- 兄弟通信
Bus;
Vuex
- 跨级通信
Bus;
Vuex;
provide/inject
$attrs/$listeners
一、前言
示例:多组件嵌套需要传递参数,通常使用vuex,但是如果只是传递数据,使用vuex不太合理,因为vuex实现的是两个组件两个值同步改变
故而Vue提供了另一种方法 使用v-bind=“$attrs”,将父组件不被认为props特性的属性传入子组件中,通常配合listeners选项一起使用,两个出现使组件之间跨组件通信不依赖vuex和bus变得简洁业务清晰
A组件跟b组件的通信:(父子组件)
如上图,abc分别是嵌套的,按照常规传参方式
- a->b通过props方式向子组件传递b->a通过在b组件中使用$emit,a组件v-on接收
- 通过全局设置vuex方式,通过computed计算属性和commit mutaion方式时间数据获取更新,达到父子通信目的
- Vue Event Bus 使用 Vue实例 实现事件监听发布,实现组件传值
一般数据不需要全局的情况父子传值 用第一种就可以解决
a组件与c组件通信(跨级组件嵌套关系)
- 使用b组件中转,a组件传递给b组件,b组件props接受再传递到c组件上,从下到上也是一次c组件emit传递,b也得emit传递,达到组件通信的效果
- 通过Vuex全局
- 使用Vue Event Bus实现监听和发布
- ps:如果只是祖先向子孙传递 不需要子孙返回 provide/inject 也可以解决
第一种方法会让代码显得冗余且不易于维护b组件只是中间站
第二种Vuex还是大材小用,只是组件数据传递,不是数据共享
第三种 如果不能很好的事件监听和发布管理 会导致数据流的混乱,不易于维护 ps:暂时没用过
第四种 只能达到向内传值 孙组件返不回去
知识点
个人理解就是 inheritAttrs 默认是true,他继承了父组件所有的属性(除了props特定的绑定) 如果不希望继承,可以改成false 但是class跟style不会受影响
attrs继承了父组件所有的属性 除了prop传递的属性,一般用在子组件的子元素
包含了负作用域所有的监听,可以配合v-on=“$listeners” 将所有事件监听器都指向组件特定子元素
实例
A组件(App.vue)
<template>
<div id="app">
<!-- 此处监听了两个事件,可以在B组件或者C组件中直接触发 -->
<child1 :pchild1="child1" :pchild2="child2" :pchild3="child3" @method1="onMethod1" @method2="onMethod2"></child1>
</div>
</template>
<script>
import Child1 from "./Child1.vue";
export default {
data() {
return {
child1:'1',
child2: 2,
child3:{
name:'child3'
}
};
},
components: { Child1 },
methods: {
onMethod1(msg1) {
console.log(`${msg1} running`);
},
onMethod2(msg2) {
console.log(`${msg2} running`);
},
},
};
</script>
B组件(Child1.vue)
<template>
<div class="child-1">
<h2>in child1</h2>
<p>props: {{ pchild1 }}</p>
<p>$attrs: {{ $attrs }}</p>
<hr/>
<!-- 通过 v-bind 绑定$attrs属性,C组件可以直接获取到A组件中传递下来的props(除了B组件中props声明的) -->
<!-- C组件中能直接触发test的原因在于 B组件调用C组件时 使用 v-on 绑定了$listeners 属性 -->
<child2 v-bind="$attrs" v-on="$listeners"></child2>
</div>
</template>
<script>
import Child2 from "./Child2.vue";
export default {
data() {
return {
child1:'child1'
};
},
components: { Child2 },
props: {
pchild1:{
type:String
}
},
inheritAttrs: false,
mounted() {
this.$emit("method1",this.child1);
},
};
</script>
C 组件 (Child2.vue)
<template>
<div class="child-2">
<h2>in child2:</h2>
<p>props: {{ pChild2 }}</p>
<p>$attrs: {{ $attrs }}</p>
<p>pchild3Name: {{ $attrs.pchild3.name }}</p>
<hr/>
</div>
</template>
<script>
export default {
data() {
return {
child2:'child2'
};
},
props: {
pChild2:{
type:String,
}
},
inheritAttrs: false,
mounted() {
this.$emit("method2",this.child2);
},
};
</script>
效果
课后小故事
假设 A组件为 祖先 它入圣后给儿子(B组件
)留了三件宝物 佛怒唐莲,暴雨梨花针 虚无吞炎 并告诫子孙(C组件
)宝物不可外借他人,且必须滴血认亲 这三件宝物都可唤祖,在儿子入圣的时候担心万一到时候爷爷不认识孙子咋办,于是留下了自己的血attrs
,告诉他有了这个你就可以继承家产了,并且告诉他你不但可以继承家产你还可以醍醐灌顶速成入圣 listeners
,故而孙组件可以调用组件的方法并且获取祖先数据