Как передать модификаторы v-model в кастомный компонент для ввода?

Родительский компонент использует стилизованный компонент инпута и передаёт ему v-model, который может включать разные модификаторы (lazy, number, trim). 

В кастомном инпуте мне нужно передать аналогичный v-model (с теми же модификаторами) во внутренний инпут. 

<b>Как это можно реализовать?</b> 

По сути, задача заключается в том, чтобы динамически сформировать что-то вроде <code class="javascript">&lt;input v-model[.lazy][.trim][.number]=" ...</code>. 

Пока что я смог извлечь <code class="javascript">modelModifiers</code> следующим образом: 
<code class="javascript">const [modelValue, modelModifiers] = defineModel()</code>. 

<a href="https://vuejs.org/api/sfc-script-setup.html#modifiers-and-transformers" rel="nofollow">Вот ссылка на пример из документации</a>, где рассматривается схожая ситуация, но там модификаторы обрабатываются вручную. Мне же хотелось бы передать их напрямую, без необходимости создавать собственные обработки модификаторов.
  • 2 ноября 2024 г. 15:42
Ответы на вопрос 3
Чтобы передать модификаторы `v-model` из родительского компонента в кастомный компонент без необходимости вручную обрабатывать их, вы можете использовать слоты или пропс для передачи значений, в зависимости от конкретной реализации. Одна из наиболее распространенных практик — это использовать `v-bind` для передачи модификаторов в ваш внутренний `<input>`. 

Вот пример, как можно это реализовать:

1. В вашем кастомном компоненте (`CustomInput.vue`), воспользуйтесь `defineModel()` для извлечения `modelValue` и `modelModifiers`, как вы уже сделали.

2. Затем вы можете использовать эти значения с помощью директивы `v-bind` на внутреннем `<input>`.

Пример кода:

```vue
<template>
  <input
    v-bind="inputBindings"
    :value="modelValue"
    @input="onInput"
  />
</template>

<script setup>
import { defineModel } from 'vue'

const { modelValue, modelModifiers } = defineModel()

// Подготовим объект с необходимыми атрибутами для <input>
const inputBindings = {
  lazy: modelModifiers.lazy,
  trim: modelModifiers.trim,
  number: modelModifiers.number,
};

// Обработчик события input
function onInput(event) {
  // Обновляем значение с учетом модификаторов
  let newValue = event.target.value;

  if (modelModifiers.trim) {
    newValue = newValue.trim();
  }
  if (modelModifiers.number) {
    newValue = Number(newValue);
  }
  
  emit('update:modelValue', newValue);
}
</script>
```

### Пояснения:
- `v-bind="inputBindings"` позволяет динамически добавить атрибуты в ваш `<input>` элемент.
- В `onInput` обработчике мы учли модификаторы `trim` и `number`, чтобы обработать вводимое значение в соответствии с ними и обновить `modelValue`.

### Использование компонента
Теперь вы можете использовать ваш кастомный компонент в родительском компоненте следующим образом:

```vue
<template>
  <CustomInput v-model.lazy="inputValue" />
</template>

<script setup>
import { ref } from 'vue'

const inputValue = ref('');
</script>
```

Таким образом, модификаторы `lazy`, `trim` и `number` будут автоматически передаваться во внутренний `<input>` вашего кастомного компонента, что избавит вас от необходимости писать обработчики для каждого модификатора.
<blockquote>Нашёл ещё <a href="https://vuejs.org/api/render-function.html#withmodifiers" rel="nofollow">функцию <code class="javascript">withModifiers</code></a>, но она только для v-on событий</blockquote> <br/> А какая разница? Это же будет внутри компонента, а снаружи v-model останется как был. Почему бы не попробовать завернуть в этот withModifiers установку нового значения? Единственное, что придётся в явном виде обрабатывать, это модификатор lazy - чтобы правильные события слушать. <a href="https://play.vuejs.org/#eNqFU9tO20AQ/ZXBqmRHMo4Kb2mStiAeQAWqUvqCkTD2ODHYu6u9GKjlf+/sbmKgQPIQxTtzzpy5dsF3IZLWYDAJpiqXldCgUBsxT1nVCC41/DlmwmgoJW8gTMb+aSnhlwHTgcQyBs5OuWEaC/t5gCWXeMkaa4J+FWDFS1nOmdLQZvVnmFl2FC6xrnkMD1zWxc5OOCLYANpbg0qT34Neooc50BqGLZLQDMLKZmhVvH2ZsaJGSR6E2RyskdeY1HwR3XzqHCvR/FIIlIeZwmjUT25iwERncoHaKgx1RdHIhih4bhpLy4riyPJ/VEojQxm5aPFacuTJrzrxfwiJDW9xa5Tp2E+H5kIPjY2oM430ApgKifOug5OL87NEaVmxRVU+Rba1I+j76dj6HbDdda2BdrfhBdYJM80tSuJwMUsDS0gDGDsJQt/K+fBb+v+V50PBvS2ChG2SOvv75OX2VnLT8YuCgjjQioZUVovkTnFGm9nZYGmQ80ZU1JBzoSsaYhpMwHmsL6PdeThxNi0Nxmt7vsT8/h37nXq0tjT4KVGhbDENBp8fvHcfXZzhI30PTirE1ITe4PyFtGDG5uhhB8bN8QXOZXvsboea91sdPdLg1boom6hF9g5PnTJ4uKH053T3k33HS1lPXXy+1I+Pu4OHSi9PeVGVFUr10ZlegZtfbP9WyGu6pwLLiiGxsY7eu8QB7WYOXyHMaacXGMJkw5W+yiiyBbm79RtEW2PoOZynN7hGnd/eYa6Te3xS0aA8Stm28/ErOnGBaC+dDi3mtytXxjWZVrmlwZtd7f8Bw/DNFQ==" rel="nofollow">Как-то так</a> : <br/> <br/> <pre><code class="javascript">const [ model, modifiers ] = defineModel();

const event = modifiers.lazy ? 'change' : 'input';
const handler = withModifiers(
  e =&gt; model.value = e.target.value,
  Object.keys(modifiers)
);</code></pre> <br/> <code class="html">&lt;input :value="model" @[event]="handler"&gt;</code>
Использовать вместо v-model отдельно :model-value :model-modifiers и событие @update:model-value не работает?
Похожие вопросы