且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Vuejs - 冒泡自定义事件

更新时间:2023-10-03 12:26:10

我知道有 4 个选项

  1. 像你一样重新发送事件
  2. 在子组件上(重复地)使用 this.$parent 来访问所需的父组件并发出事件.(请参阅下面的实现您自己的冒泡事件插件")
  3. 使用由父级提供并在子级中注入的事件总线.
  4. 使用 Vuex 存储并将事件推送到子组件中的事件队列.在应用程序的其他地方,观察新元素的反应式事件队列或将其绑定到某个东西.
  1. Re-emit events like you did
  2. Use this.$parent (repetitively) on the child component to access the desired parent and emit the event. (see "Implement your own bubbling event plugin" below)
  3. Use an event bus that is provided by the parent and injected in the children.
  4. Use a Vuex store and push events to an event queue in the child component. Somewhere else in the app, watch that reactive event queue for new elements or just bind it to something.

实现自己的冒泡事件插件

这很简单.该插件添加了一个新的 $bubble 方法,该方法向其父级发出冒泡事件.我考虑过发布一个插件来做到这一点,但它是如此简单,以至于开销不值得.

Implement your own bubbling event plugin

It's very simple. The plugin adds a new $bubble method that emits events that bubble to their parents. I considered publishing a plugin that does this, but it's so simple that the overhead is not worth it.

// Add this as a Vue plugin
Vue.use((Vue) => {
  Vue.prototype.$bubble = function $bubble(eventName, ...args) {
    // Emit the event on all parent components
    let component = this;
    do {
      component.$emit(eventName, ...args);
      component = component.$parent;
    } while (component);
  };
});

// Some nested components as an example

// note usage of "$bubble" instead of "$emit"
Vue.component('component-c', {
  template: `
    <button type="button" @click="$bubble('my-event', 'payload')">
      Emit bubbling event
    </button>`,
});

Vue.component('component-b', {
  template: `<component-c @my-event="onMyEvent" />`,
  
  methods: {
    onMyEvent(...args) {
      console.log('component-b listener: ', ...args);
    },
  },
});

Vue.component('component-a', {
  template: `<component-b @my-event="onMyEvent" />`,
  
  methods: {
    onMyEvent(...args) {
      console.log('component-a listener: ', ...args);
    },
  },
});

var vapp = new Vue({
  el: '#app',

  methods: {
    onMyEvent(...args) {
      console.log('root listener: ', ...args);
    },
  },
});

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <component-a @my-event="onMyEvent" />
</div>

事件总线如下所示:

Vue.component('dyn-menu', {
  components: {
    'menu-item': {
      template: '<li @click="itemClick">{{item.text}}</li>',
      props: ['item'],
      inject: ['eventBus'], // <-- Inject in the child
      methods: {
        itemClick() {
          // Emit the event on the event bus
          this.eventBus.$emit('dyn-menu-item-click', ['menu-item dyn-menu-item-click']);
        }
      }
    }
  },

  // ...
});

var vapp = new Vue({
  el: '#app',
  data: {
    // ...
    eventBus: new Vue(),
  },
  provide() {
    return {
      // The parent component provides the event bus to its children
      eventBus: this.eventBus,
    };
  },

  created() {
    // Listen to events on the event bus
    this.eventBus.$on('dyn-menu-item-click', this.menuClick);
  },
  methods: {
    menuClick(message) {}
  }
})

工作示例:https://jsfiddle.net/7vwfx52b/

这里列出了很多事件总线插件:https://github.com/vuejs/awesome-vue#custom-events

There are plenty of event bus plugins listed here: https://github.com/vuejs/awesome-vue#custom-events