логотип PurpleSchool
логотип PurpleSchool

Гайд на checkbox компонент во Vue

Автор

Алексей Ларионов

Введение

Checkbox — один из самых распространённых UI-компонентов, который встречается практически в каждом веб-приложении. Его используют для выбора одного или нескольких элементов из списка, для включения или выключения опций и для многих других задач. Если вы работаете с Vue, очень важно знать, как использовать стандартный чекбокс, создавать свои компоненты на его основе, контролировать его состояние, стилизовать и интегрировать со сложными структурами данных.

В этой статье вы узнаете, как с нуля использовать чекбоксы во Vue, какие нюансы стоят за двусторонней привязкой, как реализовывать кастомные чекбоксы, решать типовые задачи работы с коллекциями и валидировать вводимые значения. Примеры и пояснения позволят вам почувствовать себя увереннее при работе с этим элементом управления в проектах любого масштаба.


Основы чекбокс-компонента во Vue

Базовый синтаксис

Чекбокс во Vue реализуется очень просто с помощью стандартного input с атрибутом type="checkbox", а для связи состояния чекбокса с данными компонента используется директива v-model.

Пример базового чекбокса:

<template>
  <input type="checkbox" v-model="checked" />
  <span>Чекбокс отмечен: {{ checked }}</span>
</template>

<script>
export default {
  data() {
    return {
      checked: false // Изначально не отмечен
    }
  }
}
</script>

// Здесь мы связываем переменную checked с состоянием чекбокса. // Когда пользователь ставит или снимает галочку, значение checked меняется.

С помощью v-model вы легко добиваетесь двусторонней привязки состояния. Значение переменной автоматически обновляется, когда пользователь взаимодействует с чекбоксом.


Управление значением чекбокса

По умолчанию v-model связывает чекбокс с булевым значением. Но если стоит задача выбирать из списка сущностей или работать с массивами, это поведение можно конфигурировать.

Использование чекбокса для выбора из множества

Рассмотрим ситуацию, когда пользователь может выбрать несколько опций из списка:

<template>
  <div>
    <label v-for="item in items" :key="item">
      <input type="checkbox" :value="item" v-model="selectedItems" />
      {{ item }}
    </label>
    <div>Вы выбрали: {{ selectedItems }}</div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      items: ['Vue', 'React', 'Angular'], // Список технологий
      selectedItems: [] // Список выбранных значений
    }
  }
}
</script>

// Здесь v-model связан с массивом selectedItems. При выборе чекбокса значение value (item) добавляется или удаляется из массива.

Такой подход часто используется при генерации чекбоксов по данным, например, для фильтров или мультиселекта.

Управление значениями через true-value и false-value

Vue позволяет указать пользователю какие значения будут записываться при установке или снятии галочки:

<template>
  <input
    type="checkbox"
    v-model="status"
    true-value="yes"
    false-value="no"
  />
  <span>Статус: {{ status }}</span>
</template>

<script>
export default {
  data() {
    return {
      status: 'no' // Начальное значение
    }
  }
}
</script>

// В данном случае, если чекбокс отмечен, в переменную status запишется "yes", если снят — "no".


Однонаправленная и двусторонняя привязка

v-model по сути комбинирует передачу значения через :checked и обработчик событий @change. Вы можете реализовать такую связку и вручную, если это необходимо для особых кейсов.

// Однонаправленная привязка через :checked
<template>
  <input
    type="checkbox"
    :checked="isChecked"
    @change="onChange"
  />
</template>

<script>
export default {
  props: ['isChecked'],
  methods: {
    onChange(e) {
      // Здесь вы, например, можете вызвать props или emit
      this.$emit('update:isChecked', e.target.checked)
    }
  }
}
</script>

// Такой подход востребован при построении контролируемых компонентов.


Validating чекбоксы во Vue

Если вам нужно, чтобы пользователь обязательно поставил галочку (например, при согласии с условиями), нужна простая валидация.

<template>
  <form @submit.prevent="submit">
    <label>
      <input type="checkbox" v-model="agreed" />
      Я согласен с условиями
    </label>
    <div v-if="error" style="color: red">{{ error }}</div>
    <button type="submit">Отправить</button>
  </form>
</template>

<script>
export default {
  data() {
    return {
      agreed: false,
      error: null
    }
  },
  methods: {
    submit() {
      if (!this.agreed) {
        this.error = 'Вы должны согласиться с условиями'
      } else {
        this.error = null
        // Продолжить логику отправки
      }
    }
  }
}
</script>

// Здесь при попытке отправить форму проверяем значение agreed. Если чекбокс не отмечен, показываем ошибку.


Создание кастомного чекбокс компонента

Иногда стандартное оформление чекбокса вас не устраивает — например, нужно добавить иконку, стилизовать галочку или анимировать изменение состояния.

Кастомизация с помощью scoped slots

Вот пример простого кастомного чекбокс-компонента:

<template>
  <label class="custom-checkbox">
    <input
      type="checkbox"
      :checked="modelValue"
      @change="$emit('update:modelValue', $event.target.checked)"
      style="display: none;"
    />
    <span class="checkbox-box" :class="{ checked: modelValue }"></span>
    <slot></slot>
  </label>
</template>

<script>
export default {
  props: {
    modelValue: {
      type: Boolean,
      default: false
    }
  }
}
</script>

<style>
.custom-checkbox {
  cursor: pointer;
  display: flex;
  align-items: center;
}
.checkbox-box {
  width: 18px;
  height: 18px;
  border: 2px solid #007bff;
  border-radius: 4px;
  margin-right: 8px;
  transition: background 0.2s;
  background: #fff;
}
.checkbox-box.checked {
  background: #007bff;
  position: relative;
}
.checkbox-box.checked::after {
  content: '';
  display: block;
  width: 12px;
  height: 6px;
  border-left: 3px solid #fff;
  border-bottom: 3px solid #fff;
  position: absolute;
  left: 2px;
  top: 5px;
  transform: rotate(-45deg);
}
</style>

// Вы скрываете стандартный input, а состояние чекбокса синхронизируется через проп modelValue и событие update:modelValue. // Подключать такой компонент можно с помощью v-model:

<template>
  <CustomCheckbox v-model="checked">Я согласен с правилами</CustomCheckbox>
</template>

Управление группой чекбоксов через компонент

Если нужно сделать компонент, который управляет группой чекбоксов, реализуется примерно следующее:

<template>
  <div>
    <CustomCheckbox
      v-for="option in options"
      :key="option.value"
      :modelValue="selected.includes(option.value)"
      @update:modelValue="toggle(option.value, $event)"
    >
      {{ option.label }}
    </CustomCheckbox>
  </div>
</template>

<script>
export default {
  data() {
    return {
      selected: [],
      options: [
        { value: 'apple', label: 'Яблоко' },
        { value: 'banana', label: 'Банан' },
        { value: 'pear', label: 'Груша' }
      ]
    }
  },
  methods: {
    toggle(value, checked) {
      if (checked && !this.selected.includes(value)) {
        this.selected.push(value)
      } else if (!checked && this.selected.includes(value)) {
        this.selected = this.selected.filter(v => v !== value)
      }
    }
  }
}
</script>

// Обратите внимание, что массив выбранных значений обновляется методом toggle.


Чекбоксы с формами и сложными структурами

Checkbox часто используется вместе с более сложными формами, где данные представлены объектами, массивами или даже вложенными структурами.

Пример: чекбоксы и объекты

Бывает важно понимать, как чекбоксы работают с объектами вместо простых строковых/булевых значений.

<template>
  <div>
    <label v-for="user in users" :key="user.id">
      <input
        type="checkbox"
        :value="user"
        v-model="selectedUsers"
      />
      {{ user.name }}
    </label>
    <div>
      Выбранные: {{ selectedNames }}
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      users: [
        { id: 1, name: 'Иван' },
        { id: 2, name: 'Мария' }
      ],
      selectedUsers: []
    }
  },
  computed: {
    selectedNames() {
      return this.selectedUsers.map(u => u.name).join(', ')
    }
  }
}
</script>

// В этом случае в массив selectedUsers будут добавляться ссылки на объекты пользователя, а не только их id или имена.

Слежение за чекбоксами во вложенных структурах

Если возвращаются сложные формы, где каждая группа чекбоксов представлена вложенным объектом, рекомендуется управлять состоянием через иерархию ключей в стейте.

<template>
  <div v-for="(group, groupName) in settings" :key="groupName">
    <h4>{{ groupName }}</h4>
    <label v-for="(checked, setting) in group" :key="setting">
      <input
        type="checkbox"
        :checked="checked"
        @change="toggleSetting(groupName, setting)"
      />
      {{ setting }}
    </label>
  </div>
</template>

<script>
export default {
  data() {
    return {
      settings: {
        Общие: { уведомления: true, подписка: false },
        Безопасность: { двухфакторная: false }
      }
    }
  },
  methods: {
    toggleSetting(group, setting) {
      this.settings[group][setting] = !this.settings[group][setting]
    }
  }
}
</script>

// Здесь структура данных повторяет структуру чекбоксов, что делает синхронизацию очевидной и простой.


Динамическая генерация чекбоксов и данные из API

Часто чекбокс группы генерируются на основании данных, получаемых из API. В этом случае все работает аналогично, просто данные приходят асинхронно.

<template>
  <div>
    <label v-for="tag in tags" :key="tag.id">
      <input type="checkbox" :value="tag.id" v-model="selectedTags">
      {{ tag.name }}
    </label>
  </div>
</template>

<script>
export default {
  data() {
    return {
      tags: [],
      selectedTags: []
    }
  },
  mounted() {
    // Например, симуляция загрузки данных с сервера
    setTimeout(() => {
      this.tags = [
        { id: 1, name: 'Javascript' },
        { id: 2, name: 'Vue.js' }
      ]
    }, 1000)
  }
}
</script>

// Как видите, работа с асинхронными данными не отличается от статических случаев.


Особенности стилизации и accessibility

Стилизация

Системные чекбоксы часто выглядят по-разному в разных ОС и браузерах. Для унификации используют кастомные чекбоксы с элементом-обёрткой (span, div) и скрытым input.

input[type="checkbox"] {
  display: none; /* Скрываем стандартный чекбокс */
}
.custom-checkbox {
  width: 20px;
  height: 20px;
  border: 1px solid #000;
  display: inline-block;
  background: #fff;
  vertical-align: middle;
}
.custom-checkbox.checked {
  background: #2196F3;
}

// Важно всегда следить за доступностью! Добавляйте лэйблы и используйте атрибуты aria-checked и tabindex для кастомных чекбоксов.

Accessibility

Чтобы чекбоксы были доступны для экранных чтецов и клавиатуры, не забывайте:

  • использовать <label> для связывания подписи и input;
  • не скрывать полностью input (используйте opacity: 0, а не display: none);
  • добавлять атрибут aria-checked и обрабатывать keydown для поддержки навигации с клавиатуры в кастомных компонентах.

Интеграция с Vue Form Libraries

Если используется форма с библиотеками типа VeeValidate, vuelidate или FormKit, то чекбоксы подчиняются общим принципам работы с v-model, но следите за типом данных! Библиотека может ожидать булево значение или массив — смотрите документацию по API.

Пример использования VeeValidate:

<template>
  <Form @submit="onSubmit">
    <Field
      type="checkbox"
      name="agree"
      :value="true"
      as="input"
      v-slot="{ field }"
    >
      <input v-bind="field" />
      Я принимаю условия
    </Field>
    <ErrorMessage name="agree" />
    <button type="submit">Отправить</button>
  </Form>
</template>

// В этом примере Field управляет состоянием чекбокса и валидирует его.


Заключение

Вы познакомились с чекбоксами во Vue с разных сторон: от базового синтаксиса и работы с простыми значениями до управления массивами и объектами, создания кастомных компонентов и интеграции с формочными библиотеками. Вы знаете, как реализовать как булевые чекбоксы, так и чекбоксы для коллекций, а также стилизовать их без ущерба для доступности.


Частозадаваемые технические вопросы по теме и ответы

Как сбросить все чекбоксы сразу?

Для сброса всех чекбоксов просто очистите массив или установите булевы значения снова в false. Например: js this.selectedItems = [] // или для булевых: // this.checked = false

Как сделать чекбокс только для чтения (read-only)?

Стандартный чекбокс не поддерживает атрибут readonly, используйте disabled: vue <input type="checkbox" v-model="value" disabled> Если нужен read-only без стилистического эффекта disabled, добавьте кастомную обработку клика: vue <input type="checkbox" :checked="value" @change.prevent>

Как синхронизировать несколько чекбоксов на разных компонентах?

Используйте переменную состояния в родительском компоненте и передавайте в дочерние через props/v-model, либо работайте через Vuex/pinia для глобального состояния.

Как правильно работать с чекбоксом внутри v-for с объектами?

Лучше явно указывать ключи и связывать value с уникальным идентификатором: vue <input type="checkbox" :value="item.id" v-model="selectedIds" /> Так вы избежите багов при работе с объектами (сравнения по ссылке).

Как сделать индикатор промежуточного состояния (indeterminate)?

У input[type="checkbox"] есть свойство indeterminate: vue <input type="checkbox" ref="myCheckbox" v-model="checked" /> В mounted/updated: js this.$refs.myCheckbox.indeterminate = true Indeterminate состояние нельзя поставить через v-model, его надо задавать вручную через реф.

Стрелочка влевоИспользование директивы checked для управления состоянием чекбоксов в VueОтображение данных в виде графиков с помощью Vue ChartСтрелочка вправо

Все гайды по Vue

Руководство по валидации форм во Vue.jsИнтеграция Tiptap для создания редакторов на VueРабота с таблицами во Vue через TanStackИнструкция по установке и компонентам Vue sliderУправление пакетами Vue js с помощью npmУправление пакетами и node modules в Vue проектахКак использовать meta для улучшения SEO на VueПолный гайд по компоненту messages во Vuejs5 правил использования Inertia с Vue и LaravelРабота с модулями и пакетами в VueИнструкция по работе с grid на VueGithub для Vue проектов - подробная инструкция по хранению и совместной работеНастройка ESLint для Vue проектов и поддержка качества кодаОбработка ошибок и отладка в Vue.jsИспользование Vue Devtools для отладки и мониторинга приложенийРабота с конфигурационными файлами и скриптами VueСоздание и настройка проектов Vue с помощью Vue CLI3 способа интеграции Chart.js с Vue для создания графиковРабота с Canvas во VueИнструкция по реализации календаря во VueРабота с Ant Design Vue для создания UI на Vue
Обзор и использование утилит Vue для удобной разработкиРабота с обновлениями компонента и жизненным циклом updateРазрешение конфликтов и ошибок с помощью Vue resolveИспользование query-параметров и их обработка в маршрутах VueЗагрузка и управление состоянием загрузки в VueИспользование библиотек Vue для расширения функционалаРабота с JSON данными в приложениях VueКак работать с экземплярами компонента Instance во VueПолучение данных и API-запросы во Vue.jsЭкспорт и импорт данных и компонентов в VueОбработка событий и их передача между компонентами VuejsГайд по defineEmits на Vue 3Понимание core функционала Vue и его применениеПонимание и применение Composition API в Vue 3Понимание и работа с компилятором VueКогда и как использовать $emit и call во VueВзаимодействие с внешними API через Axios в Vue
Веб приложения на Vue архитектура и лучшие практикиИспользование Vite для быстрого старта и сборки проектов на Vue 3Работа с URL и ссылками в приложениях на VueРабота с пользовательскими интерфейсами и UI библиотеками во VueОрганизация и структура исходных файлов в проектах VueИспользование Quasar Framework для разработки на Vue с готовыми UI-компонентамиОбзор популярных шаблонов и стартовых проектов на VueИнтеграция Vue с PHP для создания динамичных веб-приложенийКак организовать страницы и маршруты в проекте на VueNuxt JS и Vue 3 для SSR приложенийСоздание серверных приложений на Vue с помощью Nuxt jsИспользование Vue Native для разработки мобильных приложенийОрганизация и управление индексной страницей в проектах VueИспользование Docker для контейнеризации приложений на VueИнтеграция Vue.js с Django для создания полноценных веб-приложенийСоздание и работа с дистрибутивом build dist Vue приложенийРабота со стилями и CSS в Vue js для красивых интерфейсовСоздание и структурирование Vue.js приложенияКак исправить ошибку cannot find module vueНастройка и сборка проектов Vue с использованием современных инструментовИнтеграция Vue с Bitrix для корпоративных решенийРазработка административных панелей на Vue js
5 библиотек для создания tree view во VueИнтеграция Tailwind CSS с Vue для современных интерфейсовИнтеграция Vue с серверной частью и HTTPS настройкамиКак обрабатывать async операции с Promise во VueИнтеграция Node.js и Vue.js для разработки приложенийРуководство по интеграции Vue js в NET проектыПримеры использования JSX во VueГайд по импорту и регистрации компонентов на VueМногоязычные приложения на Vue с i18nИнтеграция FLIR данных с Vue5 примеров использования filter во Vue для упрощения разработки3 примера реализации drag-and-drop во Vue
Управление переменными и реактивными свойствами во VueИспользование v for и slot в VueПрименение v-bind для динамической привязки атрибутов в VueУправление пользователями и их данными в Vue приложенияхСоздание и использование UI Kit для Vue приложенийТипизация и использование TypeScript в VuejsИспользование шаблонов в Vue js для построения интерфейсовИспользование Swiper для создания слайдеров в VueРабота со стилями и стилизацией в VueСтруктура и особенности Single File Components SFC в VueРабота со SCSS в проектах на Vue для стилизацииРабота со скроллингом и прокруткой в Vue приложенияхПрименение script setup синтаксиса в Vue 3 для упрощения компонентовИспользование scoped стилей для изоляции CSS в компонентах Vue3 способа улучшить навигацию Vue с push()Обработка запросов и асинхронных операций в VueПонимание и использование provide inject для передачи данных между компонентамиПередача и использование props в Vue 3 для взаимодействия компонентовПередача данных между компонентами с помощью props в Vue jsУправление property и функциями во Vue.jsРабота со свойствами компонентов VueУправление параметрами и динамическими данными во VueРабота с lifecycle-хуком onMounted во VueОсновы работы с объектами в VueПонимание жизненного цикла компонента Vue js на примере mountedИспользование модальных окон modal в Vue приложенияхИспользование методов в компонентах Vue для обработки логикиИспользование метода map в Vue для обработки массивовИспользование хуков жизненного цикла Vue для управления состоянием компонентаРабота с ключами key в списках и компонентах VueОбработка пользовательского ввода в Vue.jsРабота с изображениями и их оптимизация в VueИспользование хуков жизненного цикла в VueОрганизация сеток и гридов для верстки интерфейсов на VueСоздание и управление формами в VueОрганизация файлов и структура проекта Vue.jsКомпоненты Vue создание передача данных события и emitРабота с динамическими компонентами и данными в Vue3 способа манипулирования DOM на VueРуководство по div во VueИспользование директив в Vue и их расширенные возможностиОсновы и применение директив в VueИспользование директив и их особенности на Vue с помощью defineИспользование компонентов datepicker в Vue для выбора датОрганизация циклов и итераций во VueКак работает компиляция Vue CoreСоздание и использование компонентов в Vue JSОбработка кликов и пользовательских событий в VueИспользование классов в Vue для организации кода и компонентовИспользование директивы checked для управления состоянием чекбоксов в VueГайд на checkbox компонент во VueОтображение данных в виде графиков с помощью Vue ChartСоздание и настройка кнопок в VueСоздание и настройка кнопок в Vue приложенияхРабота с lifecycle-хуками beforeCreate и beforeMount во VueИспользование массивов и методов их обработки в VueИспользование массивов и их обработка в Vue
Использование Vuetify для создания современных интерфейсов на VueИспользование transition во VueТестирование компонентов и приложений на VueРабота с teleport для управления DOM во VueПять шагов по настройке SSR в VuejsИспользование Shadcn UI компонентов с Vue для продвинутых интерфейсовИспользование router-link для навигации в Vue RouterКак использовать require в Vue для динамического импорта модулейРабота с динамическим рендерингом и виртуальным DOM на Vue.jsИспользование ref для управления ссылками и реактивностью в Vue 3Использование Vue Pro и его преимущества для профессиональной разработкиРуководство по nextTick для работы с DOMСоздание и использование компонентов с помощью Vue js и CУправление состоянием и реактивностью через inject и provideДинамическое обновление компонентов и данных на VueГлубокое изучение документации Vue и как эффективно её использоватьИспользование Crystal с Vue для разработкиИспользование вычисляемых свойств для динамического отображения данных на Vue jsОптимизация производительности и предупреждения в Vue
Открыть базу знаний