vue3-skeleton-dir
v1.0.1
Published
Vue 3 directive library
Readme
Vue 3 Skeleton Directive
Легковесная Vue 3 директива для создания skeleton loading состояний. Простая настройка, гибкая кастомизация, TypeScript поддержка.
✨ Возможности
- 🎨 Полностью настраиваемый внешний вид
- 🔧 Простая интеграция через директиву
- 🎭 Поддержка кастомных skeleton компонентов
- 📦 Минимальный размер бандла
- 🎯 TypeScript типизация из коробки
- ⚡ Автоматическая анимация
- 🎪 CSS автоматически инжектится
📦 Установка
npm install vue3-skeleton-diryarn add vue3-skeleton-dirpnpm add vue3-skeleton-dir🚀 Быстрый старт
Глобальная регистрация
import { createApp } from 'vue'
import { vSkeleton } from 'vue3-skeleton-dir'
import App from './App.vue'
const app = createApp(App)
// Регистрируем директиву глобально
app.directive('skeleton', vSkeleton())
app.mount('#app')Локальная регистрация
<script setup lang="ts">
import { ref } from 'vue'
import { vSkeleton as vSkeletonFn } from 'vue3-skeleton-dir'
const vSkeleton = vSkeletonFn()
const isLoading = ref(true)
setTimeout(() => {
isLoading.value = false
}, 2000)
</script>
<template>
<div v-skeleton="isLoading">
<h1>Контент загружен!</h1>
<p>Этот текст появится после загрузки</p>
</div>
</template>📖 Использование
Базовое использование
<template>
<!-- Простой boolean -->
<div v-skeleton="true">Loading content...</div>
<!-- С реактивным состоянием -->
<div v-skeleton="isLoading">
{{ userData }}
</div>
</template>С кастомными опциями
<template>
<div v-skeleton="{
loading: isLoading,
width: '200px',
height: '40px',
backgroundColor: '#f3f4f6',
animation: true,
borderRadius: '8px'
}">
Custom skeleton
</div>
</template>Кастомный skeleton компонент
<script setup lang="ts">
import { defineComponent, h } from 'vue'
import { vSkeleton } from 'vue3-skeleton-dir'
// Создаём кастомный компонент
const CustomSkeleton = defineComponent({
name: 'CustomSkeleton',
props: {
width: String,
height: String,
backgroundColor: String,
animation: Boolean,
borderRadius: String
},
setup(props) {
return () => h('div', {
class: 'my-custom-skeleton',
style: {
width: props.width,
height: props.height,
background: `linear-gradient(90deg, ${props.backgroundColor} 0%, #fff 50%, ${props.backgroundColor} 100%)`,
borderRadius: props.borderRadius
}
})
}
})
const isLoading = ref(true)
</script>
<template>
<div v-skeleton="{ loading: isLoading, component: CustomSkeleton }">
Content here
</div>
</template>Глобальный кастомный компонент
import { createApp } from 'vue'
import { vSkeleton, setSkeletonComponent } from 'vue3-skeleton-dir'
import CustomSkeleton from './components/CustomSkeleton.vue'
// Устанавливаем глобальный кастомный компонент
setSkeletonComponent(CustomSkeleton)
const app = createApp(App)
app.directive('skeleton', vSkeleton())
app.mount('#app')Дефолтный компонент через конфиг
import { createApp } from 'vue'
import { vSkeleton } from 'vue3-skeleton-dir'
import CustomSkeleton from './components/CustomSkeleton.vue'
const app = createApp(App)
// Передаём дефолтный компонент в конфиг директивы
app.directive('skeleton', vSkeleton({
defaultComponent: CustomSkeleton
}))
app.mount('#app')⚙️ API
Опции директивы
| Параметр | Тип | По умолчанию | Описание |
|----------|-----|--------------|----------|
| loading | boolean | true | Показывать ли skeleton |
| width | string | '100%' | Ширина skeleton |
| height | string | '100%' | Высота skeleton |
| backgroundColor | string | '#e2e8f0' | Цвет фона |
| animation | boolean | true | Включить волновую анимацию |
| borderRadius | string | '0.25rem' | Радиус скругления углов |
| component | Component | DefaultSkeleton | Кастомный Vue компонент |
💡 Совет: При указании ширины и высоты в процентах (
width: '100%',height: '100%'), размеры рассчитываются от реального размера элемента, на котором висит директива. Не нужно вычислять размеры в пикселях вручную — просто укажите100% 100%и skeleton заполнит весь блок карточки полностью!
Функции
vSkeleton(config?: DirectiveConfig)
Создаёт директиву skeleton.
interface DirectiveConfig {
defaultComponent?: Component
}setSkeletonComponent(component: Component)
Устанавливает глобальный кастомный skeleton компонент.
import { setSkeletonComponent } from 'vue3-skeleton-dir'
import MyCustomSkeleton from './MyCustomSkeleton.vue'
setSkeletonComponent(MyCustomSkeleton)💡 Примеры использования
Карточка пользователя
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { vSkeleton } from 'vue3-skeleton-dir'
const loading = ref(true)
const user = ref(null)
onMounted(async () => {
const response = await fetch('/api/user')
user.value = await response.json()
loading.value = false
})
</script>
<template>
<div class="user-card">
<div
v-skeleton="{ loading, height: '80px', borderRadius: '50%' }"
class="avatar"
>
<img v-if="!loading" :src="user?.avatar" alt="Avatar" />
</div>
<div v-skeleton="{ loading, height: '24px', width: '150px' }">
<h2>{{ user?.name }}</h2>
</div>
<div v-skeleton="{ loading, height: '16px', width: '200px' }">
<p>{{ user?.email }}</p>
</div>
</div>
</template>Список элементов
<script setup lang="ts">
import { ref } from 'vue'
import { vSkeleton } from 'vue3-skeleton-dir'
const loading = ref(true)
const items = ref([])
// Симуляция загрузки
setTimeout(() => {
items.value = [1, 2, 3, 4, 5]
loading.value = false
}, 2000)
</script>
<template>
<div class="list">
<div
v-for="i in 5"
:key="i"
v-skeleton="loading"
class="list-item"
>
<div v-if="!loading">Item {{ items[i - 1] }}</div>
</div>
</div>
</template>📝 Лицензия
MIT © sandexplus
🤝 Contributing
Contributions, issues и feature requests приветствуются!
⭐ Поддержка
Если проект помог, поставьте звёздочку на GitHub!
