Skip to content

Двусторонняя привязка с defineModel

В Vue 3.4+ появился улучшенный способ работы с двусторонней привязкой данных через API defineModel(), который значительно упрощает создание компонентов с поддержкой v-model.

Базовое использование

vue
<!-- CustomInput.vue -->
<script setup>
// Создание двусторонней привязки
const modelValue = defineModel();
</script>

<template>
  <input 
    :value="modelValue"
    @input="modelValue = $event.target.value"
  />
</template>

<!-- Использование компонента -->
<script setup>
import { ref } from 'vue';
import CustomInput from './CustomInput.vue';

const username = ref('');
</script>

<template>
  <CustomInput v-model="username" />
  <p>Введённое значение: {{ username }}</p>
</template>

Настройка модели

vue
<script setup>
// С проверкой и значением по умолчанию
const modelValue = defineModel({
  type: String,
  default: '',
  required: true,
  validator: (value) => value.length > 3
});
</script>

Множественные модели

vue
<!-- UserForm.vue -->
<script setup>
const firstName = defineModel('firstName');
const lastName = defineModel('lastName');
</script>

<template>
  <div>
    <input 
      :value="firstName"
      @input="firstName = $event.target.value"
      placeholder="Имя"
    />
    <input 
      :value="lastName"
      @input="lastName = $event.target.value"
      placeholder="Фамилия"
    />
  </div>
</template>

<!-- Использование компонента с множественными моделями -->
<script setup>
import { ref } from 'vue';
import UserForm from './UserForm.vue';

const first = ref('');
const last = ref('');
</script>

<template>
  <UserForm 
    v-model:firstName="first"
    v-model:lastName="last"
  />
  <p>Полное имя: {{ first }} {{ last }}</p>
</template>

Модификаторы модели

vue
<script setup>
// Доступ к модификатору .trim
const modelValue = defineModel({ 
  default: '' 
});

// Получение объекта модификаторов
const modelModifiers = defineModifiers();

// Проверка наличия модификатора
const hasTrimModifier = modelModifiers.trim;
</script>

<template>
  <input 
    :value="modelValue"
    @input="
      let value = $event.target.value;
      if (modelModifiers.trim) {
        value = value.trim();
      }
      modelValue = value;
    "
  />
</template>

Использование defineModel позволяет значительно сократить количество шаблонного кода по сравнению с традиционным подходом через props и emit, делая компоненты с двусторонней привязкой более читаемыми и поддерживаемыми.