Vue之组件通信

496 阅读4分钟

一篇可以让你彻底学会组件如何通信干货文章

“滴水能把石穿透,万事功到自然成”——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实现原理

代码示意图

流程图