Dynamic Tags

Naive UI предоставляет гибкий механизм работы с компонентами тегов через n-tag и n-tag-group. Особенно полезным является создание динамических тегов, когда список элементов может изменяться в зависимости от пользовательского ввода или данных с сервера.


Основные компоненты

  • n-tag – отдельный тег с текстом, цветом и опциями удаления.
  • n-tag-group – контейнер для группы тегов, поддерживает динамическое добавление и удаление элементов.

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

<template>
  <n-tag-group>
    <n-tag v-for="tag in tags" :key="tag" closable @close="removeTag(tag)">
      {{ tag }}
    </n-tag>
  </n-tag-group>
</template>

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

const tags = ref(['Vue', 'JavaScript', 'Naive UI'])

function removeTag(tag) {
  tags.value = tags.value.filter(t => t !== tag)
}
</script>

В этом примере каждый тег можно закрыть, а список tags динамически обновляется.


Добавление новых тегов

Для динамического добавления часто используют текстовое поле (n-input) и кнопку. В Naive UI можно реализовать так:

<template>
  <n-input v-model:value="newTag" @keyup.enter="addTag" placeholder="Введите новый тег" />
  <n-button @click="addTag">Добавить</n-button>

  <n-tag-group>
    <n-tag v-for="tag in tags" :key="tag" closable @close="removeTag(tag)">
      {{ tag }}
    </n-tag>
  </n-tag-group>
</template>

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

const tags = ref(['Vue', 'JavaScript'])
const newTag = ref('')

function addTag() {
  const value = newTag.value.trim()
  if (value && !tags.value.includes(value)) {
    tags.value.push(value)
  }
  newTag.value = ''
}

function removeTag(tag) {
  tags.value = tags.value.filter(t => t !== tag)
}
</script>

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

  • Использование trim() предотвращает добавление пустых тегов.
  • Проверка !tags.value.includes(value) исключает дубли.
  • Поддержка события @keyup.enter позволяет добавлять тег по нажатию Enter.

Стилизация тегов

n-tag поддерживает кастомизацию через свойства:

  • type – визуальный тип (info, success, warning, error, default)
  • color – собственный цвет фона
  • size – размер (small, medium, large)

Пример динамического изменения цвета в зависимости от контента:

<n-tag
  v-for="tag in tags"
  :key="tag"
  closable
  :color="tagColor(tag)"
  @close="removeTag(tag)"
>
  {{ tag }}
</n-tag>

<script setup>
function tagColor(tag) {
  switch(tag.toLowerCase()) {
    case 'vue': return '#42b883'
    case 'javascript': return '#f7df1e'
    default: return '#d9d9d9'
  }
}
</script>

Динамические группы с ограничением количества тегов

Иногда нужно ограничить количество тегов, чтобы не перегружать интерфейс:

<n-tag-group>
  <n-tag
    v-for="(tag, index) in tags.slice(0, maxTags)"
    :key="tag"
    closable
    @close="removeTag(tag)"
  >
    {{ tag }}
  </n-tag>
  <span v-if="tags.length > maxTags">+{{ tags.length - maxTags }} ещё</span>
</n-tag-group>

<script setup>
const maxTags = 3
</script>
  • slice(0, maxTags) ограничивает количество отображаемых тегов.
  • Элемент +N ещё показывает количество скрытых тегов.

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

Для более сложных случаев, например с тегами, имеющими идентификатор и текст:

<n-tag-group>
  <n-tag
    v-for="tag in tags"
    :key="tag.id"
    closable
    @close="removeTag(tag.id)"
    :type="tag.type"
  >
    {{ tag.label }}
  </n-tag>
</n-tag-group>

<script setup>
const tags = ref([
  { id: 1, label: 'Vue', type: 'success' },
  { id: 2, label: 'Naive UI', type: 'info' }
])

function removeTag(id) {
  tags.value = tags.value.filter(t => t.id !== id)
}
</script>
  • Каждый тег имеет уникальный id, что облегчает удаление.
  • type позволяет визуально выделять разные категории тегов.

Интерактивное редактирование тегов

Для редактирования текста тегов можно использовать событие @click и модальное окно или n-input внутри n-tag:

<n-tag-group>
  <n-tag
    v-for="tag in tags"
    :key="tag.id"
    closable
    @close="removeTag(tag.id)"
  >
    <n-input v-model:value="tag.label" size="small" />
  </n-tag>
</n-tag-group>
  • Изменения происходят мгновенно благодаря двухстороннему связыванию v-model.
  • Можно добавлять валидацию, чтобы не допустить пустых значений.

Использование динамических тегов с API

Для интеграции с сервером динамические теги можно загружать и синхронизировать через API:

import axios from 'axios'

async function fetchTags() {
  const response = await axios.get('/api/tags')
  tags.value = response.data
}

async function saveTags() {
  await axios.post('/api/tags', tags.value)
}
  • fetchTags() загружает исходный набор тегов.
  • saveTags() сохраняет изменения на сервере.
  • Можно комбинировать с локальными изменениями через v-model.

Ключевые моменты при работе с динамическими тегами

  • Использовать v-for с уникальным :key для корректного обновления DOM.
  • Всегда проверять дубли и пустые значения при добавлении новых тегов.
  • Для сложных тегов лучше использовать массив объектов с id и label.
  • Ограничение видимых тегов улучшает восприятие интерфейса.
  • Визуальные типы и цвета помогают структурировать информацию.

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