0

我有使用 v-model 指令的自定义输入组件,因此在输入时它会发出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>
4

0 回答 0