一篇可以让你彻底学会组件如何通信干货文章
“滴水能把石穿透,万事功到自然成”——zZ先森
组件是可以复用的,且是多次的。且带有一个名字,使用的时候,就像使用HTML标签一样。 组件是可复用的Vue实例,所以他们与new Vue接收相同的选项,不同之处在于没有el。下图为组件树示意图:
为了能在模板中使用,组件必须先要注册,才能被Vue识别,分为俩种组件注册的类型:①全局注册和局部注册。全局注册的组件可以用在其被注册之后的任何 (通过new Vue
) 新创建的 Vue 根实例,也包括其组件树中的所有子组件的模板中。局部注册的组件在其子组件中不可用。
1.组件信息通讯之父传子
首先,父子组件是一个相对的概念,A组件调用了B组件,A组件为B组件的父组件,B组件为A组件的子组件。
Prop属性传递
Prop 是你可以在组件上注册的一些自定义 attribute。当一个值传递给一个 prop attribute 的时候,它就变成了那个组件实例的一个 property。 通过Prop属性传递,有俩步:
- 父组件调用子组件时,父组件通过自定义属性来传递值
<blog-post title="My journey with Vue"></blog-post>
<blog-post title="Blogging with Vue"></blog-post>
<blog-post title="Why Vue is so fun"></blog-post>
- 子组件通过props来注册接收,并将这些属性放到prop列表中
Vue.component('blog-post', {
props: ['title'],
template: '<h3>{{ title }}</h3>'
})
props中声明的属性和data一样,是响应式数据,挂载到vm实例上,可控制视图渲染
props中的一些细节问题
- 命名大小写:属性名设置为kebab-case模式,在子组件注册的时候用的是 camalCase/PasalCase 来注册接收 sup-num => supNum/SupNum;也可以直接都是小写英文来命名。
- 指定属性的类型:props:{xxx:String,…}
- 指定属性的默认值:props:{xxx:{type:String,default:’xxx’,required:true}}
- type如果是一个数组,数组内的每一项意为指定的类型皆可以
- default指定一个默认值,可以是一个函数,函数返回值是其默认值
- required表示是必须传递
- validator自定义验证规则函数:必须符合函数中指定的规则,返回true/false
- 传递的属性值默认都是字符串格式,如果想要让传递的值是数字、布尔、数组、对象等格式,我们需要使用v-bind处理
- 调用组件的时候如果设置的属性是class/style这类样式属性,VUE会默认帮我们把样式和组件的样式进行合并处理。
$attrs & $listeners
- $attrs:获取的是父组件传递进来的属性信息(不包括在PROPS中注册过的信息,排除class和style等 )一般是基于v-bind绑定的属性或者静态属性
- $listeners:获取的是父组件传递的事件行为,基于
@XXX = "zZ"
处理父子之间的信息传递
2.组件信息通讯之子改父
订阅自定义事件:调用组件的时候基于属性传递一个方法 (父)
父组件在子组件的事件池中添加了一个名为func的函数,然后子组件通过通过自身的事件池中的函数之执行。
<my-component @func='zz'></my-component>
new Vue({
methods:{
zz(value){
//=>value是this.$emit时候传递的第二个参数值
}
}
});
子组件让其事件池中的函数执行
{
methods:{
xxx(){
this.$emit('func',10);
//第一个参数为此事件池中标识名
}
}
}
创建事件总线
- 创建一个总的事件池
- 每一个组件都有自己的状态,也有自己修改状态的方法
- 把这些修改状态的方法放到总的事件池中
- 触发源头,让事件池中的方法执行
let eventBus=new Vue; //=>创建事件总线
//A组件
eventBus.$on('xxx',this.func);
//B组件
eventBus.$on('xxx',this.handle);
//c组件
EventBus.$emit('xxx', start);//触发事件 并传了一个参数start
基于provide和inject实现祖先与后代的通信
- 把后代需要用到的公共信息放到祖先provide中(provide中得数据没有挂载到vm的实例上,所以不是响应式数据,我们会创建响应式状态信息先存储公共信息,让PROVIDE中存储的是状态信息:以后只要我们把状态信息修改了,存储在祖先PROVIDE中的信息也会跟着修改;我们需要保证PROVIDE中存储的数据是可被监控的,这样的话DATA中存储的数据需要以对象的方式存储,这样才能保证对象中的每个数据也是被监控的。
{
data() {
return {
obj: {
supNum: 0,
oppNum: 0
}
};
},
provide() {
// 此方法只有第一次加载组件的时候执行一次
return {
obj: this.obj,
handle: this.handle
};
},
...
}
- 后代组件基于inject声明需要使用的数据并调取使用
{
inject:['obj'],
methods:{
func(){
let obj=this.obj;
}
}
}
基于ref实现父子组件信息通信
- ref: $refs 如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例,基于此可以快速获取和操作子组件中的数据
- children: 是获取组件所有子组件的实例,$children是一个数组集合,需要我们记住组件顺序才可以找到想要操作的组件。
- parent: 通过 $parent获得其所在父组件的实例。
VUEX
vuex:是vue中实现公共状态管理的插件。Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。能处理任何情况下的组件之间的信息通信,前提是SPA单页面(实现的是同一个页面中,组件之间的信息交互)。
- vuex实现原理
代码示意图
流程图