A
A
Anton P.2018-06-20 15:35:13
Vue.js
Anton P., 2018-06-20 15:35:13

Could you continue bubbling your own events in vue.js?

vue.js has functionality that allows you to pass the actual event to the parent component, for example $emit('selected-menu', event). But this event can only be listened to on the parent component when the child component is called.
Is it possible to somehow forward this event further (ascent), so that it would be possible to listen to it on any ancestor component, including the root one?
Code example: root component, it is not possible to listen to the event here, it does not workconsole.log('я </main-header></main-header>')

Vue.component('mian-container', {
  template: `<main-header @selected-menu="getEvent"></main-header>`,
  methods:{
    getEvent(event){
      console.log('я </main-header></main-header>')
    }
  }
})

This is a component <main-header>, here I successfully listen to the event, outputconsole.log('я </main-header></main-header>')
Vue.component('main-header', {
  template: `<main-menu @selected-menu="getEvent"></main-menu>`,
  methods:{
    getEvent(event){
      console.log('я <main-menu></main-menu>')
    }
  }
})

This is a component <main-menu>, here I am emitting an event with this.$emit('selected-menu', event);
Vue.component('main-menu', {
  template: `<ul @click="selectedMenu"> <li>Главная</li> <li>Проекты</li> </ul>`,
  methods:{
    selectedMenu(event){
      let el = event.target.closest('li');
      if(!el) {return}
      event.my_data = { el: el }
      this.$emit('selected-menu', event);
    }
  }
})

Creating a vue instance
new Vue({
  el: '#main'
})

Answer the question

In order to leave comments, you need to log in

2 answer(s)
A
Anton Shvets, 2018-06-20
@mrswylet

Scroll up 1 level: https://jsfiddle.net/6v6qhq00/40/
If only

this.$root.emit('selected-menu', data) 
this.$root.on('selected-menu', callback) // и не забыть отписаться

In general, for the exchange of data between components, there is vuex

A
Andrew, 2018-06-21
@pal-software

I started learning Vue and literally today I faced the same problem. I poked around, read, didn’t find anything, in the end I wrote down such a thing myself .. (the solution may not be so hot, but everything seems to work):
1. in the main javascript file, insert the following code at the beginning:

Vue.prototype.$popup_emit = function (event) {
    var vm = this;
    var args = toArray(arguments, 1);

    while ( vm && vm != null )
    {
        var cbs    = vm._events[event];

        if (cbs) {
            cbs = cbs.length > 1 ? toArray(cbs) : cbs;

            for (var i = 0, l = cbs.length; i < l; i++) {
                try {
                    var result = cbs[i].apply(vm, args);

                    // если обработчик вернет false, то сразу останавливаем обработку событий
                    if ( result === false )
                    {
                        return this;
                    }

                } catch (e) {
                    handleError(e, vm, ("event handler for \"" + event + "\""));
                }
            }
        }
        vm = vm.$parent;
    }
    return this;

    function toArray (list, start) {
        start = start || 0;
        var i = list.length - start;
        var ret = new Array(i);
        while (i--) {
          ret[i] = list[i + start];
        }
        return ret
      }
};

(in fact, this is the source of the standard emit method with some changes of mine)
2. instead of this.$emit(...) we now call this.$popup_emit(...) ... this event will pop up from child components to parent until will reach the very top or until one of the handlers returns false. ...
well, then you can finish it at your discretion. ...I didn’t test much, maybe some errors, but I think the idea is clear ..

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question