使用 Carousel 组件以轮播形式显示项目列表。
<script setup lang="ts">
const items = [
'https://picsum.photos/640/640?random=1',
'https://picsum.photos/640/640?random=2',
'https://picsum.photos/640/640?random=3',
'https://picsum.photos/640/640?random=4',
'https://picsum.photos/640/640?random=5',
'https://picsum.photos/640/640?random=6'
]
</script>
<template>
<UCarousel v-slot="{ item }" :items="items" class="w-full max-w-xs mx-auto">
<img :src="item" width="320" height="320" class="rounded-lg">
</UCarousel>
</template>
使用 items 属性作为数组,并使用默认插槽渲染每个项目
<script setup lang="ts">
const items = [
'https://picsum.photos/640/640?random=1',
'https://picsum.photos/640/640?random=2',
'https://picsum.photos/640/640?random=3',
'https://picsum.photos/640/640?random=4',
'https://picsum.photos/640/640?random=5',
'https://picsum.photos/640/640?random=6'
]
</script>
<template>
<UCarousel v-slot="{ item }" :items="items" class="w-full max-w-xs mx-auto">
<img :src="item" width="320" height="320" class="rounded-lg">
</UCarousel>
</template>
您还可以传入一个包含以下属性的对象数组
class?: anyui?: { item?: ClassNameValue }您可以通过在 item 上使用basis / width工具类来控制可见的项目数量。
<script setup lang="ts">
const items = [
'https://picsum.photos/468/468?random=1',
'https://picsum.photos/468/468?random=2',
'https://picsum.photos/468/468?random=3',
'https://picsum.photos/468/468?random=4',
'https://picsum.photos/468/468?random=5',
'https://picsum.photos/468/468?random=6'
]
</script>
<template>
<UCarousel v-slot="{ item }" :items="items" :ui="{ item: 'basis-1/3' }">
<img :src="item" width="234" height="234" class="rounded-lg">
</UCarousel>
</template>
使用 orientation 属性更改进度条的方向。默认为 horizontal。
<script setup lang="ts">
const items = [
'https://picsum.photos/640/640?random=1',
'https://picsum.photos/640/640?random=2',
'https://picsum.photos/640/640?random=3',
'https://picsum.photos/640/640?random=4',
'https://picsum.photos/640/640?random=5',
'https://picsum.photos/640/640?random=6'
]
</script>
<template>
<UCarousel
v-slot="{ item }"
orientation="vertical"
:items="items"
:ui="{ container: 'h-[336px]' }"
class="w-full max-w-xs mx-auto"
>
<img :src="item" width="320" height="320" class="rounded-lg">
</UCarousel>
</template>
height。使用 arrows 属性显示上一张和下一张按钮。
<script setup lang="ts">
const items = [
'https://picsum.photos/640/640?random=1',
'https://picsum.photos/640/640?random=2',
'https://picsum.photos/640/640?random=3',
'https://picsum.photos/640/640?random=4',
'https://picsum.photos/640/640?random=5',
'https://picsum.photos/640/640?random=6'
]
</script>
<template>
<UCarousel v-slot="{ item }" arrows :items="items" class="w-full max-w-xs mx-auto">
<img :src="item" width="320" height="320" class="rounded-lg">
</UCarousel>
</template>
使用 prev 和 next 属性,可以使用任何 Button 属性自定义上一张和下一张按钮。
<script setup lang="ts">
const items = [
'https://picsum.photos/640/640?random=1',
'https://picsum.photos/640/640?random=2',
'https://picsum.photos/640/640?random=3',
'https://picsum.photos/640/640?random=4',
'https://picsum.photos/640/640?random=5',
'https://picsum.photos/640/640?random=6'
]
</script>
<template>
<UCarousel
v-slot="{ item }"
arrows
:prev="{ color: 'primary' }"
:next="{ variant: 'solid' }"
:items="items"
class="w-full max-w-xs mx-auto"
>
<img :src="item" width="320" height="320" class="rounded-lg">
</UCarousel>
</template>
使用 prev-icon 和 next-icon 属性自定义按钮 Icon。默认为 i-lucide-arrow-left / i-lucide-arrow-right。
<script setup lang="ts">
defineProps<{
prevIcon?: string
nextIcon?: string
}>()
const items = [
'https://picsum.photos/640/640?random=1',
'https://picsum.photos/640/640?random=2',
'https://picsum.photos/640/640?random=3',
'https://picsum.photos/640/640?random=4',
'https://picsum.photos/640/640?random=5',
'https://picsum.photos/640/640?random=6'
]
</script>
<template>
<UCarousel
v-slot="{ item }"
arrows
:prev-icon="prevIcon"
:next-icon="nextIcon"
:items="items"
class="w-full max-w-xs mx-auto"
>
<img :src="item" width="320" height="320" class="rounded-lg">
</UCarousel>
</template>
使用 dots 属性显示一列点,用于滚动到特定幻灯片。
<script setup lang="ts">
const items = [
'https://picsum.photos/640/640?random=1',
'https://picsum.photos/640/640?random=2',
'https://picsum.photos/640/640?random=3',
'https://picsum.photos/640/640?random=4',
'https://picsum.photos/640/640?random=5',
'https://picsum.photos/640/640?random=6'
]
</script>
<template>
<UCarousel v-slot="{ item }" dots :items="items" class="w-full max-w-xs mx-auto">
<img :src="item" width="320" height="320" class="rounded-lg">
</UCarousel>
</template>
点的数量基于视图中显示的幻灯片数量
<script setup lang="ts">
const items = [
'https://picsum.photos/640/640?random=1',
'https://picsum.photos/640/640?random=2',
'https://picsum.photos/640/640?random=3',
'https://picsum.photos/640/640?random=4',
'https://picsum.photos/640/640?random=5',
'https://picsum.photos/640/640?random=6'
]
</script>
<template>
<UCarousel v-slot="{ item }" dots :items="items" :ui="{ item: 'basis-1/3' }">
<img :src="item" width="320" height="320" class="rounded-lg">
</UCarousel>
</template>
Carousel 组件实现了官方的Embla Carousel 插件.
此插件用于扩展 Embla Carousel 的自动播放功能。
使用 autoplay 属性作为布尔值或对象来配置自动播放插件.
<script setup lang="ts">
const items = [
'https://picsum.photos/468/468?random=1',
'https://picsum.photos/468/468?random=2',
'https://picsum.photos/468/468?random=3',
'https://picsum.photos/468/468?random=4',
'https://picsum.photos/468/468?random=5',
'https://picsum.photos/468/468?random=6'
]
</script>
<template>
<UCarousel
v-slot="{ item }"
loop
arrows
dots
:autoplay="{ delay: 2000 }"
:items="items"
:ui="{ item: 'basis-1/3' }"
>
<img :src="item" width="234" height="234" class="rounded-lg">
</UCarousel>
</template>
loop 属性实现无限轮播。此插件用于扩展 Embla Carousel 的自动滚动功能。
使用 auto-scroll 属性作为布尔值或对象来配置自动滚动插件.
<script setup lang="ts">
const items = [
'https://picsum.photos/468/468?random=1',
'https://picsum.photos/468/468?random=2',
'https://picsum.photos/468/468?random=3',
'https://picsum.photos/468/468?random=4',
'https://picsum.photos/468/468?random=5',
'https://picsum.photos/468/468?random=6'
]
</script>
<template>
<UCarousel
v-slot="{ item }"
loop
dots
arrows
auto-scroll
:items="items"
:ui="{ item: 'basis-1/3' }"
>
<img :src="item" width="234" height="234" class="rounded-lg">
</UCarousel>
</template>
loop 属性实现无限轮播。此插件用于扩展 Embla Carousel 的自动高度功能。它会更改轮播容器的高度,以适应视图中最高幻灯片的高度。
使用 auto-height 属性作为布尔值或对象来配置自动高度插件.
<script setup lang="ts">
const items = [
'https://picsum.photos/640/640?random=1',
'https://picsum.photos/640/320?random=2',
'https://picsum.photos/640/640?random=3',
'https://picsum.photos/640/320?random=4',
'https://picsum.photos/640/640?random=5',
'https://picsum.photos/640/320?random=6'
]
</script>
<template>
<UCarousel
v-slot="{ item }"
auto-height
arrows
dots
:items="items"
:ui="{
container: 'transition-[height]',
controls: 'absolute -top-8 inset-x-12',
dots: '-top-7',
dot: 'w-6 h-1'
}"
class="w-full max-w-xs mx-auto"
>
<img :src="item" width="320" height="320" class="rounded-lg">
</UCarousel>
</template>
transition-[height] 类来动画化高度变化。类名是 Embla Carousel 的类名切换实用插件,使您能够自动化轮播中类名的切换。
使用 class-names 属性作为布尔值或对象来配置类名插件.
<script setup lang="ts">
const items = [
'https://picsum.photos/528/528?random=1',
'https://picsum.photos/528/528?random=2',
'https://picsum.photos/528/528?random=3',
'https://picsum.photos/528/528?random=4',
'https://picsum.photos/528/528?random=5',
'https://picsum.photos/528/528?random=6'
]
</script>
<template>
<UCarousel
v-slot="{ item }"
class-names
arrows
:items="items"
:ui="{
item: 'basis-[70%] transition-opacity [&:not(.is-snapped)]:opacity-10'
}"
class="mx-auto max-w-sm"
>
<img :src="item" width="264" height="264" class="rounded-lg">
</UCarousel>
</template>
item 上添加了 transition-opacity [&:not(.is-snapped)]:opacity-10 类来动画化不透明度变化。此插件用于用渐隐过渡替换 Embla Carousel 的滚动功能。
使用 fade 属性作为布尔值或对象来配置渐隐插件.
<script setup lang="ts">
const items = [
'https://picsum.photos/640/640?random=1',
'https://picsum.photos/640/640?random=2',
'https://picsum.photos/640/640?random=3',
'https://picsum.photos/640/640?random=4',
'https://picsum.photos/640/640?random=5',
'https://picsum.photos/640/640?random=6'
]
</script>
<template>
<UCarousel
v-slot="{ item }"
fade
arrows
dots
:items="items"
class="w-full max-w-xs mx-auto"
>
<img :src="item" width="320" height="320" class="rounded-lg">
</UCarousel>
</template>
此插件用于扩展 Embla Carousel 的功能,使其能够使用鼠标/触控板滚轮导航轮播。
使用 wheel-gestures 属性作为布尔值或对象来配置滚轮手势插件.
<script setup lang="ts">
const items = [
'https://picsum.photos/468/468?random=1',
'https://picsum.photos/468/468?random=2',
'https://picsum.photos/468/468?random=3',
'https://picsum.photos/468/468?random=4',
'https://picsum.photos/468/468?random=5',
'https://picsum.photos/468/468?random=6'
]
</script>
<template>
<UCarousel
v-slot="{ item }"
loop
wheel-gestures
:items="items"
:ui="{ item: 'basis-1/3' }"
>
<img :src="item" width="234" height="234" class="rounded-lg">
</UCarousel>
</template>
您可以使用emblaApi函数scrollTo在轮播下方显示缩略图,允许您导航到特定幻灯片。
<script setup lang="ts">
const items = [
'https://picsum.photos/640/640?random=1',
'https://picsum.photos/640/640?random=2',
'https://picsum.photos/640/640?random=3',
'https://picsum.photos/640/640?random=4',
'https://picsum.photos/640/640?random=5',
'https://picsum.photos/640/640?random=6'
]
const carousel = useTemplateRef('carousel')
const activeIndex = ref(0)
function onClickPrev() {
activeIndex.value--
}
function onClickNext() {
activeIndex.value++
}
function onSelect(index: number) {
activeIndex.value = index
}
function select(index: number) {
activeIndex.value = index
carousel.value?.emblaApi?.scrollTo(index)
}
</script>
<template>
<div class="flex-1 w-full">
<UCarousel
ref="carousel"
v-slot="{ item }"
arrows
:items="items"
:prev="{ onClick: onClickPrev }"
:next="{ onClick: onClickNext }"
class="w-full max-w-xs mx-auto"
@select="onSelect"
>
<img :src="item" width="320" height="320" class="rounded-lg">
</UCarousel>
<div class="flex gap-1 justify-between pt-4 max-w-xs mx-auto">
<div
v-for="(item, index) in items"
:key="index"
class="size-11 opacity-25 hover:opacity-100 transition-opacity"
:class="{ 'opacity-100': activeIndex === index }"
@click="select(index)"
>
<img :src="item" width="44" height="44" class="rounded-lg">
</div>
</div>
</div>
</template>
| 属性 | 默认值 | 类型 |
|---|---|---|
as | 'div' | any此组件应渲染为的元素或组件。 |
prev | { size: 'md', color: 'neutral', variant: 'link' } | Omit<ButtonProps, LinkPropsKeys>配置启用箭头时的上一张按钮。 |
prevIcon | appConfig.ui.icons.arrowLeft | any上一张按钮中显示的图标。 |
next | { size: 'md', color: 'neutral', variant: 'link' } | Omit<ButtonProps, LinkPropsKeys>配置启用箭头时的下一张按钮。 |
nextIcon | appConfig.ui.icons.arrowRight | any下一张按钮中显示的图标。 |
arrows | false | boolean显示上一张和下一张按钮以滚动轮播。 |
dots | false | boolean显示点以滚动到特定幻灯片。 |
orientation | 'horizontal' | "vertical" | "horizontal"轮播的方向。 |
items | CarouselItem[]
| |
autoplay | false | boolean | Partial<CreateOptionsType<OptionsType>>启用自动播放插件 |
autoScroll | false | boolean | Partial<CreateOptionsType<OptionsType>>启用自动滚动插件 |
autoHeight | false | boolean | Partial<CreateOptionsType<{ active: boolean; breakpoints: { [key: string]: Omit<Partial<any>, "breakpoints">; }; }>>启用自动高度插件 |
classNames | false | boolean | Partial<CreateOptionsType<OptionsType>>启用类名插件 |
fade | false | boolean | Partial<CreateOptionsType<{ active: boolean; breakpoints: { [key: string]: Omit<Partial<any>, "breakpoints">; }; }>>启用渐隐插件 |
wheelGestures | false | boolean | WheelGesturesPluginOptions启用滚轮手势插件
|
align | 'center' | "start" | "center" | "end" | (viewSize: number, snapSize: number, index: number): number |
containScroll | 'trimSnaps' | false | "trimSnaps" | "keepSnaps" |
slidesToScroll | 1 | number | "auto" |
dragFree | false | boolean |
dragThreshold | 10 | number |
inViewThreshold | 0 | number | number[] |
循环 | false | boolean |
skipSnaps | false | boolean |
duration | 25 | number |
startIndex | 0 | number |
watchDrag | true | false | true | (emblaApi: EmblaCarouselType, evt: PointerEventType): boolean | void |
watchResize | true | false | true | (emblaApi: EmblaCarouselType, entries: ResizeObserverEntry[]): boolean | void |
watchSlides | true | false | true | (emblaApi: EmblaCarouselType, mutations: MutationRecord[]): boolean | void |
watchFocus | true | false | true | (emblaApi: EmblaCarouselType, evt: FocusEvent): boolean | void |
active | true | boolean |
breakpoints | {} | { [key: string]: Omit<Partial<CreateOptionsType<{ align: AlignmentOptionType; axis: AxisOptionType; container: string | HTMLElement | null; slides: string | HTMLElement[] | NodeListOf<HTMLElement> | null; containScroll: ScrollContainOptionType; direction: AxisDirectionOptionType; slidesToScroll: SlidesToScrollOptionType; dragFree: boolean; dragThreshold: number; inViewThreshold: number | number[] | undefined; loop: boolean; skipSnaps: boolean; duration: number; startIndex: number; watchDrag: DragHandlerOptionType; watchResize: ResizeHandlerOptionType; watchSlides: SlidesHandlerOptionType; watchFocus: FocusHandlerOptionType; }>>, "breakpoints">; } |
ui | { root?: ClassNameValue; viewport?: ClassNameValue; container?: ClassNameValue; item?: ClassNameValue; controls?: ClassNameValue; arrows?: ClassNameValue; prev?: ClassNameValue; next?: ClassNameValue; dots?: ClassNameValue; dot?: ClassNameValue; } |
| 插槽 | 类型 |
|---|---|
default | { item: CarouselItem; index: number; } |
| 事件 | 类型 |
|---|---|
select | [selectedIndex: number] |
您可以使用useTemplateRef.
<script setup lang="ts">
const carousel = useTemplateRef('carousel')
</script>
<template>
<UCarousel ref="carousel" />
</template>
这将使您能够访问以下内容
| 名称 | 类型 |
|---|---|
emblaRef | Ref<HTMLElement | null> |
emblaApi | Ref<EmblaCarouselType | null> |
export default defineAppConfig({
ui: {
carousel: {
slots: {
root: 'relative focus:outline-none',
viewport: 'overflow-hidden',
container: 'flex items-start',
item: 'min-w-0 shrink-0 basis-full',
controls: '',
arrows: '',
prev: 'absolute rounded-full',
next: 'absolute rounded-full',
dots: 'absolute inset-x-0 -bottom-7 flex flex-wrap items-center justify-center gap-3',
dot: [
'cursor-pointer size-3 bg-accented rounded-full',
'transition'
]
},
variants: {
orientation: {
vertical: {
container: 'flex-col -mt-4',
item: 'pt-4',
prev: 'top-4 sm:-top-12 left-1/2 -translate-x-1/2 rotate-90 rtl:-rotate-90',
next: 'bottom-4 sm:-bottom-12 left-1/2 -translate-x-1/2 rotate-90 rtl:-rotate-90'
},
horizontal: {
container: 'flex-row -ms-4',
item: 'ps-4',
prev: 'start-4 sm:-start-12 top-1/2 -translate-y-1/2',
next: 'end-4 sm:-end-12 top-1/2 -translate-y-1/2'
}
},
active: {
true: {
dot: 'data-[state=active]:bg-inverted'
}
}
}
}
}
})
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nuxt/ui/vite'
export default defineConfig({
plugins: [
vue(),
ui({
ui: {
carousel: {
slots: {
root: 'relative focus:outline-none',
viewport: 'overflow-hidden',
container: 'flex items-start',
item: 'min-w-0 shrink-0 basis-full',
controls: '',
arrows: '',
prev: 'absolute rounded-full',
next: 'absolute rounded-full',
dots: 'absolute inset-x-0 -bottom-7 flex flex-wrap items-center justify-center gap-3',
dot: [
'cursor-pointer size-3 bg-accented rounded-full',
'transition'
]
},
variants: {
orientation: {
vertical: {
container: 'flex-col -mt-4',
item: 'pt-4',
prev: 'top-4 sm:-top-12 left-1/2 -translate-x-1/2 rotate-90 rtl:-rotate-90',
next: 'bottom-4 sm:-bottom-12 left-1/2 -translate-x-1/2 rotate-90 rtl:-rotate-90'
},
horizontal: {
container: 'flex-row -ms-4',
item: 'ps-4',
prev: 'start-4 sm:-start-12 top-1/2 -translate-y-1/2',
next: 'end-4 sm:-end-12 top-1/2 -translate-y-1/2'
}
},
active: {
true: {
dot: 'data-[state=active]:bg-inverted'
}
}
}
}
}
})
]
})