Библиотека Naive UI предоставляет обширный набор готовых компонентов для создания интерфейсов на Vue 3. Один из мощных инструментов, который делает эту библиотеку гибкой, — это возможность расширять базовые компоненты, добавляя собственное поведение и стили, сохраняя при этом совместимость с исходными API.
В Naive UI каждый компонент реализован как Vue-компонент с хорошо структурированными props, slots и events. Расширение базового компонента может происходить несколькими способами:
Композиция (Composition) Использование базового компонента внутри нового, оборачивая его дополнительной логикой или стилями. Этот подход безопасен и сохраняет все внутренние возможности компонента.
<template>
<n-button :type="type" @click="handleClick">
<slot />
</n-button>
</template>
<script setup>
import { NButton } from 'naive-ui'
defineProps({
type: {
type: String,
default: 'primary'
}
})
const handleClick = () => {
console.log('Кастомный клик!')
}
</script>
В этом примере создаётся новый компонент, который наследует
функционал NButton, но добавляет кастомный
обработчик событий.
Использование extends Можно
напрямую расширять компонент через опцию extends в Vue.
Этот метод удобен для переопределения props и
методов:
import { NButton } from 'naive-ui'
export default {
extends: NButton,
methods: {
handleClick() {
console.log('Расширенный клик');
this.$emit('click')
}
}
}
Такой подход позволяет полностью контролировать внутреннее поведение компонента, но требует аккуратного обращения с внутренними методами и состояниями.
style и classNaive UI использует CSS Variables для стилизации. Расширяя компонент,
можно переопределять стили через props class и
style, а также через provideTheme для
глобальных изменений:
<template>
<n-button class="my-button">
Расширенная кнопка
</n-button>
</template>
<style scoped>
.my-button {
background-color: #4caf50;
color: white;
border-radius: 12px;
}
</style>
Для более глубокой кастомизации компонентов Naive UI предоставляет возможность работы с theme overrides:
import { createTheme, NButton } from 'naive-ui'
const customTheme = createTheme({
Button: {
borderRadius: '16px',
colorPrimary: '#ff5722'
}
})
app.use(NButton, { theme: customTheme })
Такой подход позволяет создавать единый визуальный стиль для всех компонентов приложения без дублирования CSS.
Слоты — ключевой механизм расширения компонентов. Они позволяют вставлять собственный контент внутрь базового компонента, не меняя его внутреннюю логику.
Пример расширенной панели с пользовательским заголовком:
<template>
<n-card>
<template #header>
<h3>Кастомный заголовок</h3>
</template>
<p>Содержимое карточки</p>
</n-card>
</template>
<script setup>
import { NCard } from 'naive-ui'
</script>
Слоты можно комбинировать с props и events, создавая полностью кастомизированные компоненты, которые остаются совместимыми с Naive UI.
Иногда требуется добавить глобальную логику к стандартным компонентам, например, обработку ошибок, анимацию или асинхронные действия. Для этого создаются обертки:
<template>
<n-button :loading="loading" @click="handleAsyncClick">
<slot />
</n-button>
</template>
<script setup>
import { ref } from 'vue'
import { NButton } from 'naive-ui'
const loading = ref(false)
const handleAsyncClick = async () => {
loading.value = true
await new Promise(resolve => setTimeout(resolve, 2000))
loading.value = false
console.log('Асинхронная операция завершена')
}
</script>
В этом примере расширенный NButton автоматически
обрабатывает асинхронные действия, не затрагивая исходный API
кнопки.
Composition API позволяет создавать наборы функций и реактивных состояний, которые можно подключать к любому компоненту:
// useCustomButton.js
import { ref } from 'vue'
export function useCustomButton() {
const clicked = ref(false)
const handleClick = () => {
clicked.value = !clicked.value
console.log('Состояние кнопки:', clicked.value)
}
return { clicked, handleClick }
}
<template>
<n-button @click="handleClick">
{{ clicked ? 'Активна' : 'Не активна' }}
</n-button>
</template>
<script setup>
import { useCustomButton } from './useCustomButton'
import { NButton } from 'naive-ui'
const { clicked, handleClick } = useCustomButton()
</script>
Такой подход позволяет повторно использовать расширенную логику на разных компонентах без дублирования кода.
Naive UI полностью поддерживает TypeScript, и расширение компонентов с типами повышает надежность кода:
import { NButton, ButtonProps } from 'naive-ui'
import { defineComponent } from 'vue'
export default defineComponent({
extends: NButton,
props: {
...NButton.props,
customProp: {
type: Boolean,
default: false
}
},
setup(props: ButtonProps & { customProp: boolean }) {
return () => <NButton {...props}>Расширенная кнопка</NButton>
}
})
Использование TypeScript позволяет проверять совместимость пропсов и предотвращать ошибки при расширении базовых компонентов.
Расширение базовых компонентов Naive UI объединяет композицию, слоты, кастомные темы и логические обертки, создавая мощные, повторно используемые и гибкие элементы интерфейса. Это позволяет строить сложные интерфейсы с единым стилем и поведением, не теряя преимуществ готовых решений библиотеки.