В Naive UI композиция компонентов является ключевым подходом для построения гибких и масштабируемых интерфейсов. Библиотека построена с учётом модульности, что позволяет создавать сложные UI из небольших, переиспользуемых компонентов. Основная идея композиции заключается в объединении нескольких компонентов, их вложенности и управлении состоянием через props, slots и events.
Слоты в Naive UI позволяют вставлять внутрь компонентов произвольный контент, не нарушая их внутреннюю структуру. Основные типы слотов:
Пример использования именованного слота с компонентом
NCard:
import { NCard, NButton } from 'naive-ui'
export default {
setup() {
return () => (
<NCard title="Профиль пользователя">
{{
header: () => <h3>Информация о пользователе</h3>,
default: () => <p>Имя: Иван Иванов</p>,
footer: () => <NButton>Редактировать</NButton>
}}
</NCard>
)
}
}
Здесь заголовок, тело и подвал карты реализованы через отдельные слоты, что позволяет легко менять их содержимое.
Props дают возможность настраивать поведение компонентов без изменения их внутренней логики. В Naive UI большинство компонентов поддерживают детальную настройку через объектные и булевы props.
Например, компонент NButton:
<NButton type="primary" size="large" disabled={false}>
Сохранить
</NButton>
Использование props для передачи состояния позволяет создавать композиции компонентов, где родитель управляет состоянием дочерних элементов, сохраняя независимость их внутренней реализации.
Naive UI использует стандартные события Vue для передачи данных от дочернего компонента к родительскому. Основные механизмы:
onUpdate:prop – синхронизация значений props.@event – реакция на действия
пользователя.Пример с компонентом NInput и двусторонней
привязкой:
import { ref } from 'vue'
import { NInput } from 'naive-ui'
export default {
setup() {
const username = ref('')
return () => (
<NInput v-model:value={username.value} placeholder="Введите имя" />
)
}
}
Использование v-model:value автоматически связывает
состояние родителя с дочерним компонентом, обеспечивая реактивное
обновление интерфейса.
Композиция позволяет создавать новые компоненты на основе
существующих, добавляя дополнительные слои логики или визуальные
элементы. Например, создание кастомного UserCard:
import { NCard, NButton, NAvatar } from 'naive-ui'
export default {
props: {
user: Object
},
setup(props) {
const editUser = () => {
console.log('Редактирование пользователя', props.user.name)
}
return () => (
<NCard>
{{
header: () => <h3>{props.user.name}</h3>,
default: () => (
<div>
<NAvatar src={props.user.avatar} />
<p>{props.user.email}</p>
</div>
),
footer: () => <NButton onCl ick={editUser}>Редактировать</NButton>
}}
</NCard>
)
}
}
Такой подход позволяет повторно использовать шаблон
NCard и добавлять уникальную логику для каждого типа
карточки.
provide и injectДля глубокой вложенности компонентов Naive UI поддерживает передачу
данных через provide и inject, что особенно
полезно для глобального состояния внутри композиции. Пример:
import { provide, inject, ref } from 'vue'
export const ThemeProvider = {
setup(_, { slots }) {
const theme = ref('light')
provide('theme', theme)
return () => slots.default()
}
}
export const ThemedButton = {
setup() {
const theme = inject('theme')
return () => <NButton type={theme.value === 'dark' ? 'info' : 'primary'}>Кнопка</NButton>
}
}
Таким образом, компоненты, вложенные в ThemeProvider,
автоматически получают доступ к глобальному состоянию темы без
необходимости пробрасывать props через каждый уровень.
На уровне логики Naive UI и Vue 3 позволяет использовать композиционные функции для повторного использования реактивных блоков:
import { ref, computed } from 'vue'
export function useCounter() {
const count = ref(0)
const increment = () => count.value++
const double = computed(() => count.value * 2)
return { count, increment, double }
}
Компонент может использовать useCounter для добавления
функционала счётчика:
import { NButton } from 'naive-ui'
import { useCounter } from './useCounter'
export default {
setup() {
const { count, increment, double } = useCounter()
return () => (
<div>
<p>Счётчик: {count.value}</p>
<p>Удвоенное значение: {double.value}</p>
<NButton onCl ick={increment}>Увеличить</NButton>
</div>
)
}
}
Такой подход позволяет отделять логику от представления и создавать более чистые и поддерживаемые компоненты.
Naive UI предоставляет мощные инструменты для композиции компонентов через слоты, props, события и реактивные функции. Использование этих механизмов позволяет строить сложные интерфейсы, сохраняя модульность, переиспользуемость и чистоту кода, а также легко управлять состоянием и логикой компонентов на любом уровне вложенности.