Vue: $emit with multiple arguments loses data with inline listener utilizing $event

Created on 26 Apr 2017  ·  3Comments  ·  Source: vuejs/vue

Version

2.2.6

Reproduction link

https://jsfiddle.net/psycketom/50wL7mdz/29927/

Steps to reproduce

  • Component emits with multiple arguments for payload: $emit('event', first, second, arbitrary), as per documentation.
  • Parent listens to the event via inline statement @event="listener($event)".
  • Notice how listener does not get full payload, but only the first value.

What is expected?

Full event payload, either as an array or other means.

What is actually happening?

Only the first value is passed.


I ran into this by creating a list of components with v-for, listening to an event and I had to pass index parameter to the listener: @event="listener(index, $event).

Maybe my use case is meant to be solved differently (bound data attribute?!), if so, I wouldn't mind some guidance.

Most helpful comment

Use arguments: https://jsfiddle.net/50wL7mdz/30115/

Note the spread syntax will be transpiled when using *.vue components, but not if you use in-browser compilation.

All 3 comments

Use arguments: https://jsfiddle.net/50wL7mdz/30115/

Note the spread syntax will be transpiled when using *.vue components, but not if you use in-browser compilation.

Is ...arguments still working for people? When I run @myevent="$emit('myevent', ...arguments)" to re-emit and event I get an error in the console TypeError: "vm is undefined" using the latest vue-template-compiler and vue.

This is the part of my transpiled code that is the source of the error

            on: {
              myevent: function($event) {
                var i = arguments.length,
                  argsArray = Array(i)
                while (i--) argsArray[i] = arguments[i]
                return _vm.$emit.apply(
                  void 0,
                  ["myevent"].concat(argsArray)
                )
              }
            }

And this is the part of the Vue code that actually throws the TypeError on the 5th line vm._events[lowerCaseEvent]. I think it's because of the void 0 above is setting undefined to the value of vm below. Any idea where the problem is coming from?

Vue.prototype.$emit = function (event) {
    var vm = this;
    if (process.env.NODE_ENV !== 'production') {
      var lowerCaseEvent = event.toLowerCase();
      if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) {
        tip(
          "Event \"" + lowerCaseEvent + "\" is emitted in component " +
          (formatComponentName(vm)) + " but the handler is registered for \"" + event + "\". " +
          "Note that HTML attributes are case-insensitive and you cannot use " +
          "v-on to listen to camelCase events when using in-DOM templates. " +
          "You should probably use \"" + (hyphenate(event)) + "\" instead of \"" + event + "\"."
        );
      }
    }
    var cbs = vm._events[event];
    if (cbs) {
      cbs = cbs.length > 1 ? toArray(cbs) : cbs;
      var args = toArray(arguments, 1);
      var info = "event handler for \"" + event + "\"";
      for (var i = 0, l = cbs.length; i < l; i++) {
        invokeWithErrorHandling(cbs[i], vm, args, vm, info);
      }
    }
    return vm
  };

@yyx990803 I'm seeing the same error as @rightaway when trying to use ...arguments - is there some new magic to use or is this indeed a regression?

Was this page helpful?
0 / 5 - 0 ratings