У меня есть пользовательский компонент ввода, который использует директиву 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>