vue学习之组件之间的通讯

202 阅读1分钟

1.父组件 => 子组件

.属性props
// child
props:  { msg: String }

// parent
<HelloWorld msg="Hello"/>
.引用refs

2.子组件 => 父组件:自定义事件

// child
this.$emit('add', good)

//  parent
<Cart  @add="cartAdd($event)"></Cart>

3.兄弟组件之间:通过共同祖辈

通过共同的祖辈组件搭桥,$parent或$root
//  brother1
this.$parent.$on('foo', handle)

// brother2
this.$parent.$emit('foo')

4.祖先和后代之间

由于嵌套层数过多,传递props不切实际,vue提供了provide/inject API完成该任务
provide/inject:能够实现祖先给后代传值
// ancestor
provide() {
   return {foo: 'foo'}
}

// descendant
inject: ['foo']

dispatch:后代给祖先传值
//  定义一个dispatch方法,指定要派发的事件名称和数据
function dispatch(eventName, data) {
    let  = this.$parent
    // 只要还存在父元素就继续往上查找
    while (parent) {
          if (parent) {
              parent.$emit(eventName, data)
              // 递归查找父元素
              parent = parent.$parent
          } else {
                break
          }
    }
}

//  使用HelloWorld.vue
<h1 @click="dispatch('hello', 'hello, world')">{{msg}}</h1>

// App.vue
this.$on('hello', this.sayHello)

5.任意两个组件之间:事件总线或vuex

事件总线:创建一个Bus类负责事件派发、监听和回调管理
// Bus:事件派发、监听和回调管理
class Bus{
  constructor() {
    // {
    //   eventName1:[fn1,fn2],
    //   eventName2:[fn3, fn4]
    // }
    this.callbacks = {}
  }
  $on(name, fn) {
    this.callbacks[name] = this.callbacks[name] || []
    this.callbacks[name].push(fn)
  }
  $emit(name, args) {
    if(this.callbacks[name]) {
      this.callbacks[name].forEach(cb => cb(args))
    }
  }
}


// main.js
// Vue.prototype.$bus  =  new Bus()
Vue.prototype.$bus  =  new Vue()

// child1
this.$bus.$on('foo', handle)

// child2
this.$bus.$emit('foo')

实践中可以用Vue代替Bus,因为它已经实现了相应功能

vuex:创建唯一的全局数据管理store,通过它管理数据并通知组件状态变更