admin管理员组

文章数量:1183123

In jQuery you can bind multiple events by doing something like this:

$('#myDiv').on('touchstart mousedown', // more code here

And as far as I understand this will listen for touchstart OR mousedown simultaneously. But I can't work out how to do the equivalent with Vue. I can only do @touchstart="doSomething()" or @mousedown="doSomething()". Am I missing something obvious? Thanks

In jQuery you can bind multiple events by doing something like this:

$('#myDiv').on('touchstart mousedown', // more code here

And as far as I understand this will listen for touchstart OR mousedown simultaneously. But I can't work out how to do the equivalent with Vue. I can only do @touchstart="doSomething()" or @mousedown="doSomething()". Am I missing something obvious? Thanks

Share Improve this question asked Dec 18, 2018 at 1:36 Ben ClarkeBen Clarke 1,2874 gold badges19 silver badges32 bronze badges
Add a comment  | 

3 Answers 3

Reset to default 21

1. With Event Modifiers

If you are relying on events, you could try binding with event modifiers and sort of chain them inline. Something like:

<a @click.stop="doThis" @click.right="showContextMenu"></a>

2. Attaching events programmatically

Or, you could create your list of events and their respective implementations to attach with and do the loop with v-on, a workaround from this post:

created() {
    const EVENTS = [
      {name: 'my-event1', callback: () => console.log('event1')},
      {name: 'my-event2', callback: () => console.log('event2')},
      {name: 'my-event3', callback: () => console.log('event3')}
    ]

    for (let e of EVENTS) {
      this.$on(e.name, e.callback); // Add event listeners
    }
  }
  
<button @click="$emit('my-event1')">Raise event1</button>
<button @click="$emit('my-event2')">Raise event2</button>
<button @click="$emit('my-event3')">Raise event3</button>

3. v-on multiple values

Otherwise, just like you can do v-bind on multiple values, you can actually do the same with v-on for events.

<div id="mydDiv" v-on="handlers"></div>

// ...

data() {
  const vm = this;
  
  return {
    handlers: {
      mousedown: vm.divMousedown,
      touchstart: vm.divTouchstart
    }
  }
},

methods: {
  divMousedown() {
    console.log('event: mousedown');
  },
  divTouchstart() {
    console.log('event: touched');
  }
}

If you need to break down the handlers by type of event, try examining the type while the event is being fired, so in your case, since touchstart seems to also trigger mousedown, perhaps:

methods: {
  onTouched(evt) {
    evt.preventDefault();

    if (evt.type === 'mousedown') {
        // handle mousedown
    }
    else if (evt.type === 'touchstart') {
        // ...
    }
  }
}

Note: You might want to call preventDefault() on touchmove rather than touchstart. That way, mouse events can still fire and things like links will continue to work.

No you are not missing anything obvious. "touchstart mousedown" is a short-hand notation provided by jQuery for convenience. Vue does not provide a similar convenience (probably because the event binding syntax for attrs can already get pretty hairy with all the provided options).

The correct method would be as you stated, using two separate attributes: @touchstart="doSomething()" or @mousedown="doSomething()"

Binding to multiple events is not supported by vue on purpose because of inherent limitations in attribute names and the desire to avoid runtime overhead.

If you absolutely must have multi-event bindings, a custom directive would be the way to go.

(The following code is shamelessly copied from the linked JSFiddle because SO has disallowed linking to fiddles without code in the answer)

function functionWrapper(e) {
  /* add filters to handle event type before propagating to callback function for custom event handler */
  e.target.__handler__.fn(e)
}

Vue.directive('multiEvent', {
  bind: function(el, binding, vnode) {
    el.__handler__ = binding.value
    binding.value.evt.forEach(e => el.addEventListener(e, functionWrapper))
  },
  unbind: function(el, binding) {
    el.__handler__.evt.forEach(e => el.removeEventListener(e, functionWrapper))
    el.__handler__ = null
  }
})

Usage:

<input v-multi-event="{ evt: ['click', 'blur', 'change', 'keydown'], fn: someCallback }">

本文标签: javascriptBind multiple events to von directive in VueStack Overflow