Как я могу изменить полезную нагрузку события в директиве? - PullRequest
0 голосов
/ 23 января 2019

У меня есть пользовательский компонент ввода, который использует директиву v-модели, поэтому при вводе он генерирует событие input со значением и директиву v-mask, которая изменяет значение путем согласования текущего входного значения с маской и передачи другого input событие с измененным значением. Однако этот подход запускает два input события и переключает два изменения модели - одно необработанное и одно замаскированное. Могу ли я изменить существующее значение input в директиве?

const maskDirective = (() => {
      const state = new Map();
      return {
        bind: (el) => {
          const element = el instanceof HTMLInputElement ? el : el.querySelector('input');
          const textMaskInput = createTextMaskInputElement({
            inputElement: element,
            mask: TextMasks.phoneNumber,
          });
          state.set('element', element);
          state.set('input', textMaskInput);
        },
        update: () => {
          const textMaskInput = state.get('input');
          const element = state.get('element');
          const {
            state: { previousConformedValue },
          } = textMaskInput;
          textMaskInput.update();
          // otherwise there's call stack size exceeded error, because it constantly fires input event from component, catches it, and fires event from directive
          if (previousConformedValue !== element.value) {
            const event = new Event('input', { bubbles: true });
            element.dispatchEvent(event);
          }
        },
      };
    })();
<template>
  <div
    :class="{ 'is-disabled': disabled }"
    class="c-base-input"
  >
    <input
      ref="control"
      v-bind="$attrs"
      :class="{
        'has-leading-icon': $slots['leading-icon'],
        'has-trailing-icon': $slots['trailing-icon'],
        'has-prepend-content': $slots['prepend'],
        'has-append-content': $slots['append'],
        'has-value': value !== null,
      }"
      :disabled="disabled"
      :value="value"
      :type="type"
      class="c-base-input__control"
      @input="onInput($event.target.value)"
    >
    <div
      v-if="$slots['leading-icon']"
      class="c-base-input__icon is-leading"
    >
      <slot name="leading-icon" />
    </div>
    <div
      v-if="$slots['trailing-icon']"
      class="c-base-input__icon is-trailing"
    >
      <slot name="trailing-icon" />
    </div>
  </div>
</template>

<script>
export default {
  props: {
    value: {
      type: String,
      default: null,
    },
    disabled: {
      type: Boolean,
      default: false,
    },
    type: {
      type: String,
      default: 'text',
      validator: value => ['text', 'tel', 'email', 'password'].indexOf(value) !== -1,
    },
  },
  methods: {
    onInput(value) {
      if (value === '') {
        this.$emit('input', null);
      } else {
        this.$emit('input', value);
      }
    },
  },
};
</script>
...