Миграция с Ant Design Vue

При переходе с Ant Design Vue (AntD Vue) на Naive UI важно понимать различия в архитектуре компонентов, стилевых подходах и API. Несмотря на визуальное сходство некоторых элементов, Naive UI предлагает более декларативный и реактивный подход, основанный на Composition API и функциональных возможностях Vue 3.

Структура компонентов и пропсы

AntD Vue использует в основном props + slots для настройки компонентов, часто с вложенной структурой конфигураций через объекты. В Naive UI акцент смещён в сторону упрощённого API и реактивности:

  • Многие пропсы Naive UI являются реактивными и могут быть напрямую связаны с состоянием компонента через ref или reactive.
  • Для передачи сложных конфигураций используются props с функциями, а не только объекты с вложенными ключами.
  • Naive UI поддерживает динамическую тему и глобальные конфигурации через provideConfig, чего в AntD Vue нет в явном виде.

Пример различий для кнопки:

// Ant Design Vue
<a-button type="primary" :disabled="isDisabled">Кнопка</a-button>

// Naive UI
<n-button type="primary" :disabled="isDisabled">Кнопка</n-button>

На первый взгляд это простая замена тега, но Naive UI также позволяет задавать стилевую реактивность через пропсы size и theme:

<n-button :size="buttonSize" :type="buttonType">Кнопка</n-button>

Работа с формами

Формы в AntD Vue строятся через <a-form> и <a-form-item>, а в Naive UI — через <n-form> и <n-form-item>. Основное отличие:

  • Валидация: Naive UI использует схему rules аналогично AntD Vue, но обработка событий более реактивна, с поддержкой Composition API.
  • Состояние формы: в Naive UI для хранения значений формы применяется объект ref или reactive, что облегчает привязку к компонентам.

Пример миграции формы:

// Ant Design Vue
<a-form :model="formData" :rules="rules">
  <a-form-item label="Имя" prop="name">
    <a-input v-model:value="formData.name" />
  </a-form-item>
</a-form>

// Naive UI
<n-form :model="formData" :rules="rules">
  <n-form-item label="Имя" path="name">
    <n-input v-model:value="formData.name" />
  </n-form-item>
</n-form>

Ключевые моменты:

  • prop в AntD Vue → path в Naive UI.
  • v-model:value используется везде, что унифицирует привязку данных.

Таблицы и списки

AntD Vue: <a-table> с массивом колонок и слотов для кастомизации.

Naive UI: <n-data-table> с более декларативным API:

  • columns — массив объектов, каждый объект описывает ключ, заголовок, слот или функцию рендера.
  • События сортировки и фильтрации обрабатываются через sorter и filters в объекте колонки, но также поддерживается реактивная привязка состояния.

Пример колонки с кастомным рендером:

// Naive UI
const columns = [
  {
    title: 'Имя',
    key: 'name',
    render(row) {
      return h('strong', row.name)
    }
  },
  {
    title: 'Возраст',
    key: 'age',
    sorter: (a, b) => a.age - b.age
  }
]

Особенность Naive UI: возможность использовать функциональные слоты напрямую через render, что упрощает динамическую генерацию контента.

Модальные окна и уведомления

В AntD Vue модальные окна создаются через <a-modal> и методы типа this.$message.

Naive UI предлагает программные API, которые упрощают вызов компонентов вне шаблона:

import { createDiscreteApi } from 'naive-ui'

const { message, dialog } = createDiscreteApi(['message', 'dialog'])

// Сообщение
message.success('Операция выполнена')

// Модальное окно
dialog.info({
  title: 'Информация',
  content: 'Содержимое модального окна'
})

Примечание:

  • Программный подход уменьшает необходимость держать состояние модального окна в компоненте.
  • createDiscreteApi позволяет создать независимые экземпляры для сообщений, уведомлений, диалогов, подтверждений.

Темизация и глобальные настройки

Naive UI предоставляет provideConfig для управления глобальными настройками, что упрощает миграцию с AntD Vue, где для темы требовалось подключать отдельные стили:

import { createApp } from 'vue'
import { create, NButton } from 'naive-ui'

const naive = create({
  components: [NButton],
  theme: {
    common: {
      primaryColor: '#1DA57A'
    }
  }
})

const app = createApp(App)
app.use(naive)
app.mount('#app')
  • Можно менять цвета и размеры компонентов глобально.
  • Легко подключать пользовательские темы и настраивать локальные компоненты.

События и реактивность

Naive UI полностью ориентирован на Composition API:

  • Все события можно перехватывать через @update:value или v-model:value.
  • Прямое взаимодействие с состоянием через ref/reactive сокращает количество boilerplate кода.
  • Поддержка watchEffect позволяет реагировать на любые изменения формы или таблицы без сложных методов жизненного цикла.

Миграция и рекомендации

  • Компоненты 1:1: большинство базовых элементов (Button, Input, Form, Table) имеют прямой аналог.
  • Сложные компоненты (Tree, Cascader, Select) требуют внимания к API, особенно к слотам и обработчикам событий.
  • Валидация форм: перенести rules и validator с минимальными изменениями, только обновив prop → path.
  • Программные методы: заменить $message и $modal на createDiscreteApi для полной совместимости с Composition API.

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

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