Компоненты обработчиков событий Vue

У меня есть следующие обработчики событий Vue с contenteditable:

<div contentEditable="true"
v-on:keyup="changed($event, current, 0)"
v-on:paste="changed($event, current, 0)"
v-on:blur="changed($event, current, 0)"
v-on:delete="changed($event, current, 0)"
v-on:focused="changed($event, current, 0)"></div>

Однако у меня много мест, где я называю тот же код, и код становится длинным и подробным. Есть ли способ объединить обработчики событий? Что-то вроде:

v-on:keyup:paste:blur:delete:focused?

Ответ 1

Вы можете создать свою настраиваемую директиву для этой цели. Этот образец может помочь вам:

Vue.directive('wrap-on', {
  bind: function(el, binding, vnode) {
    // Keep function to remove the event later.
    el.wrappedEventFunctions = el.wrappedEventFunctions || {};
    el.wrappedEventFunctions[binding.rawName] = binding.value;

    for (var key in binding.modifiers) {
      // Check if element is a vue component
      if (vnode.componentInstance) {
        vnode.componentInstance.$on(key, binding.value);
      } else {
        el.addEventListener(key, binding.value);
      }
    }
  },
  unbind: function(el, binding, vnode) {
    for (var key in binding.modifiers) {
      if (vnode.componentInstance) {
        vnode.componentInstance.$off(key, el.wrappedEventFunctions[binding.rawName]);
      } else {
        el.removeEventListener(key, el.wrappedEventFunctions[binding.rawName]);
      }
    }
  }
})

Эта директива добавит обработчики событий к элементу. Он проверяет, является ли элемент компонентом vue; если он является компонентом vue, он регистрирует события через $on. Если он не является компонентом vue, он использует addEventListener. Вы можете изменить это поведение, если хотите.

И использование похоже:

<input v-wrap-on.click.keydown="mixedCallback" />

Или:

<some-custom-component v-wrap-on.click.keydown="mixedCallback">
    ...
</some-custom-component>

Ответ 2

Я не думаю, что есть способ, в настоящее время, комбинировать прослушиватели событий, как вы описываете.

Что вы можете сделать, так это сделать этот div своим компонентом-оболочкой (например, "editable-wrapper" ) и испустить одно событие change:

<div
  contentEditable="true"
  v-on:keyup="$emit('change', {$event, current} )"
  v-on:paste="$emit('change', {$event, current} )"
  v-on:blur="$emit('change', {$event, current} )"
  v-on:delete="$emit('change', {$event, current} )"
  v-on:focused="$emit('change', {$event, current} )">
</div>

И тогда вам нужно будет только прослушать одно событие изменения на компоненте (data - это объект с параметрами $event и current):

<editable-wrapper @change="changed(data)"></editable-wrapper>