轮播组件
一个使用 Embla 构建的支持动效和滑动的轮播组件。
关于
该轮播组件基于 Embla Carousel 库构建。
安装
pnpm dlx shadcn-vue@latest add carousel
用法
<script setup lang="ts">
import {
Carousel,
CarouselContent,
CarouselItem,
CarouselNext,
CarouselPrevious,
} from '@/components/ui/carousel'
</script>
<template>
<Carousel>
<CarouselContent>
<CarouselItem>...</CarouselItem>
<CarouselItem>...</CarouselItem>
<CarouselItem>...</CarouselItem>
</CarouselContent>
<CarouselPrevious />
<CarouselNext />
</Carousel>
</template>示例
尺寸
要设置轮播项的尺寸,你可以在 <CarouselItem /> 上使用 basis 工具类。
示例
// 轮播容器宽度的33%。
<Carousel>
<CarouselContent>
<CarouselItem class="basis-1/3">...</CarouselItem>
<CarouselItem class="basis-1/3">...</CarouselItem>
<CarouselItem class="basis-1/3">...</CarouselItem>
</CarouselContent>
</Carousel>响应式
// 小屏幕为50%,大屏幕为33%。
<Carousel>
<CarouselContent>
<CarouselItem class="md:basis-1/2 lg:basis-1/3">...</CarouselItem>
<CarouselItem class="md:basis-1/2 lg:basis-1/3">...</CarouselItem>
<CarouselItem class="md:basis-1/2 lg:basis-1/3">...</CarouselItem>
</CarouselContent>
</Carousel>间距
要设置轮播项之间的间距,我们在 <CarouselItem /> 上使用 pl-[VALUE] 工具类,并在 <CarouselContent /> 上使用负的 -ml-[VALUE] 工具类。
原因: 我曾尝试在 CarouselContent 上使用 gap 属性或 grid 布局,但这需要大量计算和脑力劳动才能精确控制间距。我发现使用 pl-[VALUE] 和 -ml-[VALUE] 工具类要容易得多。
如果你有需要,你可以随时在自己的项目中调整此项。
示例
<template>
<Carousel>
<CarouselContent class="-ml-4">
<CarouselItem class="pl-4">
...
</CarouselItem>
<CarouselItem class="pl-4">
...
</CarouselItem>
<CarouselItem class="pl-4">
...
</CarouselItem>
</CarouselContent>
</Carousel>
</template>响应式
<template>
<Carousel>
<CarouselContent class="-ml-2 md:-ml-4">
<CarouselItem class="pl-2 md:pl-4">
...
</CarouselItem>
<CarouselItem class="pl-2 md:pl-4">
...
</CarouselItem>
<CarouselItem class="pl-2 md:pl-4">
...
</CarouselItem>
</CarouselContent>
</Carousel>
</template>方向
使用 orientation 属性来设置轮播组件的方向。
<Carousel orientation="vertical | horizontal">
...
</Carousel>缩略图
选项
你可以使用 opts 属性向轮播组件传递选项。更多信息请参阅 Embla Carousel 文档。
<template>
<Carousel
:opts="{
align: 'start',
loop: true,
}"
>
<CarouselContent>
<CarouselItem>...</CarouselItem>
<CarouselItem>...</CarouselItem>
<CarouselItem>...</CarouselItem>
</CarouselContent>
</Carousel>
</template>API
方法一
在 <Carousel /> 组件上使用 @init-api 发射 (emit) 方法来设置 API 实例。
方法二
你可以通过在 <Carousel /> 组件上设置模板引用 (template ref) 来访问它。
<script setup>
const carouselContainerRef = ref<InstanceType<typeof Carousel> | null>(null)
function accessApi() {
carouselContainerRef.value?.carouselApi.on('select', () => {})
}
</script>
<template>
<Carousel ref="carouselContainerRef">
...
</Carousel>
</template>事件
你可以使用 API 监听事件。要获取 API 实例,请在 <Carousel /> 组件上使用 @init-api 发射方法。
<script setup>
import { nextTick, ref, watch } from 'vue'
import { useCarousel } from '@/components/ui/carousel'
const api = ref<CarouselApi>()
function setApi(val: CarouselApi) {
api.value = val
}
const stop = watch(api, (api) => {
if (!api)
return
// 仅监听一次,或者使用 @vueuse/core 中的 watchOnce()
nextTick(() => stop())
api.on('select', () => {
// 在 select 事件时执行某些操作。
})
})
</script>
<template>
<Carousel @init-api="setApi">
...
</Carousel>
</template>有关使用事件的更多信息,请参阅 Embla Carousel 文档。
插槽属性
你可以使用 <Carousel v-slot="slotProps" /> 组件中的 v-slot 指令获取响应式的插槽属性(如 carouselRef, canScrollNext..Prev, scrollNext..Prev),以扩展功能。
<template>
<Carousel v-slot="{ canScrollNext, canScrollPrev }">
...
<CarouselPrevious v-if="canScrollPrev" />
<CarouselNext v-if="canScrollNext" />
</Carousel>
</template>插件
你可以使用 plugins 属性为轮播组件添加插件。
pnpm add embla-carousel-autoplay
<script setup lang="ts">
import Autoplay from 'embla-carousel-autoplay'
</script>
<template>
<Carousel
class="w-full max-w-xs"
:plugins="[Autoplay({
delay: 2000,
})]"
>
...
</Carousel>
</template>有关使用插件的更多信息,请参阅 Embla Carousel 文档。