1.0.3 • Published 5d ago
@punish/carousel
Licence
MIT
Version
1.0.3
Deps
0
Size
34 kB
Vulns
0
Weekly
0
Slider 组件
一个功能强大的轮播滑块组件,支持触摸拖拽、无限循环、自定义样式和 RTL(从右到左)布局。
功能特性
- 轻量级,仅依赖 Vue 3
- 支持触摸/鼠标拖拽交互
- 无限循环滚动
- 支持初始索引设置
- 响应式设计
- 完全可自定义样式
- 支持 RTL(从右到左)布局
- 平滑的动画过渡
- 内置分页器
- 支持暴露宽度显示相邻项
安装
npm install @punish/carousel注意: import "@punish/carousel/dist/style.css"; // 如果需要样式 (SSR OR SSG 建议引入, 避免页面样式闪烁)
优势: 无需手动引入样式文件 且 按需加载
基础使用
<template>
<Slider :items="items" @change="handleChange">
<template #default="{ item, active }">
<div :class="{ 'item-active': active }">
{{ item }}
</div>
</template>
</Slider>
</template>
<script setup>
import { Slider } from "@punish/carousel";
const items = ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5"];
const handleChange = (index) => {
console.log("当前索引:", index);
};
</script>Props 属性
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
items |
T[] |
[] |
要显示的数据数组 |
initialIndex |
number |
0 |
初始显示的索引位置 |
threshold |
number |
20 |
拖拽阈值(像素),超过此值触发切换 |
gap |
number |
0 |
滑块之间的间距(像素) |
duration |
number |
300 |
动画持续时间(毫秒) |
itemClass |
string |
'' |
列表项的自定义类名 |
activeItemClass |
string |
'' |
活动项的自定义类名 |
displayCount |
number |
1 |
同时显示的滑块数量 |
exposureWidth |
number |
0 |
暴露宽度,显示相邻项的部分宽度 |
paginationClass |
string |
'' |
分页器容器的自定义类名 |
paginationItemClass |
string |
'' |
分页器项的自定义类名 |
activePaginationItemClass |
string |
'' |
活动分页器项的自定义类名 |
paginationGap |
number |
24 |
分页器项之间的间距(像素) |
paginationVisible |
boolean |
true |
是否显示分页器 |
dir |
'ltr' | 'rtl' |
undefined |
布局方向,ltr 为从左到右,rtl 为从右到左 |
Events 事件
| 事件名 | 参数 | 说明 |
|---|---|---|
change |
(index: number) |
当前索引变化时触发 |
Methods 方法
通过 ref 可以访问以下方法:
| 方法名 | 参数 | 说明 |
|---|---|---|
moveTo |
(index: number) |
移动到指定索引 |
next |
() |
移动到下一项 |
prev |
() |
移动到上一项 |
Slots 插槽
| 插槽名 | 作用域参数 | 说明 |
|---|---|---|
default |
{ item: T, active: boolean } |
自定义滑块内容 |
使用示例
基础示例
<template>
<Slider :items="items">
<template #default="{ item, active }">
<div class="slide-item" :class="{ active }">
{{ item }}
</div>
</template>
</Slider>
</template>
<script setup>
import { Slider } from "@punish/carousel";
const items = ["Slide 1", "Slide 2", "Slide 3"];
</script>
<style>
.slide-item {
width: 100%;
height: 200px;
display: flex;
align-items: center;
justify-content: center;
background: #f0f0f0;
border-radius: 8px;
}
.slide-item.active {
background: #007bff;
color: white;
}
</style>设置初始索引
<template>
<Slider :items="items" :initial-index="2">
<template #default="{ item }">
<div class="slide-item">{{ item }}</div>
</template>
</Slider>
</template>自定义间距和动画
<template>
<Slider :items="items" :gap="20" :duration="500">
<template #default="{ item }">
<div class="slide-item">{{ item }}</div>
</template>
</Slider>
</template>显示多个项目
<template>
<Slider :items="items" :display-count="3" :exposure-width="50">
<template #default="{ item, active }">
<div class="slide-item" :class="{ active }">
{{ item }}
</div>
</template>
</Slider>
</template>
<style>
.slide-item {
height: 150px;
background: #f0f0f0;
display: flex;
align-items: center;
justify-content: center;
border-radius: 8px;
}
.slide-item.active {
background: #007bff;
color: white;
transform: scale(1.05);
}
</style>使用方法控制
<template>
<div>
<Slider ref="sliderRef" :items="items">
<template #default="{ item }">
<div class="slide-item">{{ item }}</div>
</template>
</Slider>
<div class="controls">
<button @click="prev">上一个</button>
<button @click="next">下一个</button>
<button @click="moveTo(0)">回到第一个</button>
</div>
</div>
</template>
<script setup>
import { ref } from "vue";
import { Slider } from "@punish/carousel";
const sliderRef = ref(null);
const items = ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5"];
const prev = () => sliderRef.value?.prev();
const next = () => sliderRef.value?.next();
const moveTo = (index) => sliderRef.value?.moveTo(index);
</script>RTL(从右到左)布局
<template>
<Slider :items="items" dir="rtl">
<template #default="{ item }">
<div class="slide-item">{{ item }}</div>
</template>
</Slider>
</template>自定义样式
<template>
<Slider
:items="items"
item-class="custom-item"
active-item-class="custom-active"
pagination-class="custom-pagination"
pagination-item-class="custom-dot"
active-pagination-item-class="custom-dot-active"
>
<template #default="{ item, active }">
<div class="slide-content">
<h3>{{ item.title }}</h3>
<p>{{ item.description }}</p>
</div>
</template>
</Slider>
</template>
<script setup>
import { Slider } from "@punish/carousel";
const items = [
{ title: "标题 1", description: "描述 1" },
{ title: "标题 2", description: "描述 2" },
{ title: "标题 3", description: "描述 3" },
];
</script>
<style>
.custom-item {
transition: all 0.3s ease;
}
.custom-active {
transform: scale(1.1);
}
.custom-pagination {
gap: 16px;
}
.custom-dot {
width: 40px;
height: 4px;
background: #ddd;
border-radius: 2px;
}
.custom-dot-active {
background: #007bff;
}
</style>隐藏分页器
<template>
<Slider :items="items" :pagination-visible="false">
<template #default="{ item }">
<div class="slide-item">{{ item }}</div>
</template>
</Slider>
</template>监听变化事件
<template>
<Slider :items="items" @change="handleChange">
<template #default="{ item }">
<div class="slide-item">{{ item }}</div>
</template>
</Slider>
<p>当前索引: {{ currentIndex }}</p>
</template>
<script setup>
import { ref } from "vue";
import { Slider } from "@punish/carousel";
const items = ["Item 1", "Item 2", "Item 3"];
const currentIndex = ref(0);
const handleChange = (index) => {
currentIndex.value = index;
console.log("切换到:", index);
};
</script>注意事项
- 无限循环:当项目数量大于等于
displayCount时,组件会自动启用无限循环功能。 - 触摸交互:组件支持触摸和鼠标拖拽,可以通过
threshold属性调整触发切换的阈值。 - 响应式:组件会根据容器宽度自动调整滑块大小。
- RTL 支持:在 RTL 模式下,所有交互(拖拽、动画、分页器)都会自动适配从右到左的布局。
浏览器兼容性
- Chrome/Edge (最新版本)
- Firefox (最新版本)
- Safari (最新版本)
- 移动端浏览器(支持触摸事件)
License
MIT