vue系列--比較全的vue組件間通訊

Vue組件間通訊

1.props和$emit是最經常使用的,用於父子組件

2. 引用ref

<Child ref="child" />
// 使用子組件的屬性
this.$refs.child.xxx

3. 使用$children和$parent

父組件調用子組件
image.pnghtml

this.$children[0].xxx = xxx

子組件調用父組件vue

this.$parent.xxx = xxx

4. 兄弟組件,經過共同祖輩組件搭橋

this.$parent.$on(eventName, handler);

this.$parent.$emit(eventName, data);

5. 根據第3和第4種方法能夠獲得啓發,使用本身寫一個emitter用於向上通知和向下廣播

// 向父組件通知事件
Vue.prototype.$dispatch = function(eventName, data) {
  let parent = this.$parent;
  while (parent) {
      parent.$emit(eventName, data);
      parent = parent.$parent;
  }
}

// 向全部子組件通知事件
function broadcast() {
  if (this.$children && this.$children.length) {
      const args = Array.from(arguments);
      const eventName = args[0];
      const data = args.slice(1);
      this.$children.forEach(child => {
          child.$emit(eventName, ...data);
          broadcast.apply(child, args);
      })
  }
}

Vue.prototype.$broadcast = function() {
  broadcast.apply(this, Array.from(arguments));
}

6. 祖先和後代,能夠使用provide和inject,官方例子不建議修改,最好傳初始值後就不改變

// 祖先
provide() {
  return {
    form: this
  }
}

// 後代
inject: ['form']

7. 祖先和後代還能夠使用$attrs和$listeners

<!-- 中間的組件,$attrs承接父組件的props,$listeners監聽子組件的事件 -->
  <component v-bind="$attrs" v-on="$listeners" />

8. 任意兩個組件之間,能夠使用事件總線eventBus或者Vuex(Vuex單獨講解)

// 使用Vue快速定義bus
Vue.prototype.bus = new Vue();

// 自定義bus
export default class Bus {
  constructor() {
    this.onCache = {};
    this.emitCache = {};
    this.paramCache = {};
  }

  $on(eventName, handler) {
    if (!this.onCache[eventName]) {
      this.onCache[eventName] = [];
    }
    this.onCache[eventName].push(handler);
    if (this.paramCache[eventName]) {
      handler(...this.paramCache[eventName])
    }
  }

  $emit(eventName, ...data) {
    if (this.onCache[eventName]) {
      this.onCache[eventName].forEach(fn => {
        fn(...data);
      });
    }
    this.paramCache[eventName] = data;
  }

  $remove(eventName, fn) {
    if (this.onCache[eventName]) {
      if (fn) {
        for(let i = 0, len = this.onCache[eventName].length; i < len; i++) {
          if (fn === this.onCache[eventName][i]) {
            this.onCache[eventName].splice(i, 1);
            break;
          }
        }
      } else {
        this.onCache[eventName] = undefined;
        this.paramCache[eventName] = undefined;
        this.$emitCache[eventName] = undefined;
      }
    }
  } 
}

Vue.prototype.$bus = new Bus();

使用上面的自定義總線的,在監聽以後,在組件銷燬以前記得remove掉git

created() {
  this.$bus.$on('busEvent', this.onBusEventHandler);
}

beforeDestroy() {
    this.$bus.$remove('busEvent', this.onBusEventHandler);
}

github地址能查看emitter和eventbus的用法
f146fd0f29397065e9faa76a06bf1e9.pnggithub

相關文章
相關標籤/搜索