组件通信是现在网页应用当中常见的需求,根据通信的主体不同可以分为以下几个大类:
- 父子组件之间通信
- 祖先组件与后代组件(不限层级)的通信
- 任意组件通信
父子通信
props
用于父组件向子组件传递数据
// child{props: {name: String}}<div>{{name}}</div>// parent<child name="Bill" />
$attrs
同样是父组件向子组件传递数据,与props相比较,$attrs的属性无需声明即可读取
// child<div>{{$attrs.name}}</div>// parent<child name="Bill" />
批量传递:常见的用法还有父组件通过 v-bind="$attrs" 直接将自身的 $attrs 传递给子组件
// app<parent name="Bill" height="180" weight="99"/>// parent<div><child v-bind="$attrs" /></div>
$listeners
父组件向子组件传递的事件,包括原生事件和自定义事件
// parent<div><child @click="handleClick" @custom="handleCustom"/></div>// childthis.$listeners.click // function handleClick
同样$listeners也能通过上面的方式批量传递给下一层的组件
// app<parent @custom="handleCustom"/>// parent<div><child v-on="$listeners" /></div>
$children
父组件访问子组件的内容
// child{data() {return {value: 1}}}// parentthis.$children[0].value
$refs
父组件获取子组件的DOM节点引用
// child<div>child</div>// parent<div><child ref="c"/></div>this.$refs.c
自定义事件
用于子组件向父组件传递数据
// child{onChange() {this.$emit('change', this.value)}}// parent<child @change="handleChange(e)"/>
祖先后代通信
provide/inject
祖先向后代传递数据,祖先组件声明provide的值,后代通过inject获取到来自祖先的值
// ancestor{provide: {name: 'Bill'}}// descendant{inject: ['name']}
$root
全局通信
EventBus事件总线
这个事件总线可以是自己实现,也可以直接使用vue实例。使用Vue实例作为事件总线更为强大,因为它不仅能实现事件监听与派发,还能实现全局的数据响应式。
手动实现版本:
class Bus {constructor() {this.callbacks = {}}$on(type, handler) {this.callbacks[type] = this.callbacks[type] || []this.callbacks[type].push(handler)}$off(type, handler) {if (this.callbacks[type]) {this.callbacks[type] = this.callbacks.filter(fn => fn !== handler)}}$emit(type, ...args) {this.callbacks[type] && this.callbacks[type].forEach(handler => handler(...args))}}Vue.prototype.$bus = new Bus()
vue版本
Vue.prototype.$bus = new Vue()
Vuex
创建全局的store,通过它来获取数据与处理数据,另开一篇文章详细说
