50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | DoubleVerticalSlider(双垂直滑块)

📅 我们继续 50 个小项目挑战!------ DoubleVerticalSlider组件

仓库地址:https://github.com/SunACong/50-vue-projects

项目预览地址:https://50-vue-projects.vercel.app/


使用 Vue 3 的 Composition API(<script setup>)结合 TailwindCSS 创建一个全屏、左右联动的垂直轮播组件。左侧为文字内容,右侧为图片展示,两者通过按钮控制上下滑动切换。

这种设计非常适合用于企业官网首页、产品介绍页、作品集展示等需要视觉冲击力的页面。


🎯 组件目标

  • 创建一个全屏垂直轮播组件
  • 左右区域内容联动滑动
  • 支持点击按钮切换当前 Slide
  • 使用 Vue 响应式变量管理状态
  • 使用 TailwindCSS 快速构建布局和动画
  • 实现优雅的滑动过渡效果

⚙️ 技术实现点

技术点 描述
Vue 3 <script setup> 使用响应式变量管理当前 slide 索引
ref 响应式变量 控制当前激活的 slide 索引 (activeSlideIndex)
动态类绑定 :class 控制当前 slide 的层级和动画状态
内联样式绑定 :style 动态设置每个 slide 的背景色或图片及位移动画
按钮事件绑定 @click 触发上一页/下一页切换
TailwindCSS 布局类 构建全屏容器、左右分栏、居中对齐
TailwindCSS 过渡类 添加平滑的滑动动画

🧱 组件实现

模板结构 <template>

html 复制代码
<template>
    <div class="relative flex h-screen w-screen overflow-hidden">
        <!-- 左侧 -->
        <div class="relative h-full w-[35%] overflow-hidden">
            <div
                v-for="(slide, index) in leftSlides"
                :key="index"
                class="absolute inset-0 flex flex-col items-center justify-center text-white transition-all duration-500 ease-in-out"
                :class="[index === activeSlideIndex ? 'z-10' : 'pointer-events-none z-0']"
                :style="{
                    backgroundColor: slide.bgColor,
                    transform: `translateY(${-(index - activeSlideIndex) * 100}%)`,
                }">
                <h1 class="-mt-8 mb-2 text-4xl">{{ slide.title }}</h1>
                <p class="text-lg">{{ slide.description }}</p>
            </div>

            <!-- 向下按钮 -->
            <div class="absolute top-1/2 right-0 z-20 -translate-y-1/2">
                <button
                    class="rounded-l-md bg-white p-4 text-gray-500 shadow hover:text-black"
                    @click="changeSlide('down')">
                    👇
                </button>
            </div>
        </div>

        <!-- 右侧 -->
        <div class="relative h-full w-[65%] overflow-hidden">
            <div
                v-for="(slide, index) in rightSlides"
                :key="index"
                class="absolute inset-0 h-full w-full bg-cover bg-center bg-no-repeat transition-all duration-500 ease-in-out"
                :class="[index === activeSlideIndex ? 'z-10' : 'pointer-events-none z-0']"
                :style="{
                    backgroundImage: `url(${slide.imageUrl})`,
                    transform: `translateY(${(index - activeSlideIndex) * 100}%)`,
                }"></div>

            <!-- 向上按钮 -->
            <div class="absolute top-1/2 left-0 z-20 -translate-y-1/2">
                <button
                    class="rounded-r-md bg-white p-4 text-gray-500 shadow hover:text-black"
                    @click="changeSlide('up')">
                    👆
                </button>
            </div>
        </div>
    </div>
</template>

脚本逻辑 <script setup>

js 复制代码
<script setup>
import { ref } from 'vue'

const activeSlideIndex = ref(0)

const leftSlides = [
    { title: 'Flying eagle', description: 'in the sunset', bgColor: '#FFB866' },
    { title: 'Lonely castle', description: 'in the wilderness', bgColor: '#252E33' },
    { title: 'Bluuue Sky', description: "with it's mountains", bgColor: '#2A86BA' },
    { title: 'Nature flower', description: 'all in pink', bgColor: '#FD3555' },
]

const rightSlides = [
    {
        imageUrl:
            'https://images.unsplash.com/photo-1508768787810-6adc1f613514?auto=format&fit=crop&w=1350&q=80',
    },
    {
        imageUrl:
            'https://images.unsplash.com/photo-1519981593452-666cf05569a9?auto=format&fit=crop&w=715&q=80',
    },
    {
        imageUrl:
            'https://images.unsplash.com/photo-1486899430790-61dbf6f6d98b?auto=format&fit=crop&w=1002&q=80',
    },
    {
        imageUrl:
            'https://images.unsplash.com/photo-1510942201312-84e7962f6dbb?auto=format&fit=crop&w=1050&q=80',
    },
]

function changeSlide(direction) {
    if (direction === 'up') {
        activeSlideIndex.value = (activeSlideIndex.value + 1) % leftSlides.length
    } else {
        activeSlideIndex.value =
            (activeSlideIndex.value - 1 + leftSlides.length) % leftSlides.length
    }
}
</script>

🔍 重点效果实现

✅ 全屏容器布局

我们使用了以下结构创建全屏容器:

html 复制代码
<div class="relative flex h-screen w-screen overflow-hidden">

这样可以确保整个组件占满浏览器视口,同时防止滚动条出现。

💡 左右区域联动滑动

通过 transform: translateY(...) 来实现滑动动画:

js 复制代码
transform: `translateY(${-(index - activeSlideIndex) * 100}%)`

左侧向上滑动时,文字向上;右侧向下,图片向上,形成"联动"视觉效果。

🎮 按钮控制滑动方向

通过两个按钮分别控制上一张和下一张:

js 复制代码
function changeSlide(direction) {
    if (direction === 'up') {
        activeSlideIndex.value = (activeSlideIndex.value + 1) % leftSlides.length
    } else {
        activeSlideIndex.value =
            (activeSlideIndex.value - 1 + leftSlides.length) % leftSlides.length
    }
}

实现了循环切换功能,避免索引越界。


🎨 TailwindCSS 样式重点讲解

类名 作用
flex h-screen w-screen 全屏 Flex 容器
overflow-hidden 防止内容溢出
absolute inset-0 绝对定位,覆盖父容器
transition-all duration-500 ease-in-out 平滑动画过渡
bg-cover, bg-center, bg-no-repeat 图片自适应背景
text-white, text-4xl 文字样式
rounded-l-md, p-4, hover:text-black 按钮样式
top-1/2 -translate-y-1/2 居中垂直定位按钮

这些 TailwindCSS 类帮助我们快速构建了一个美观、响应式的全屏轮播组件。


📁 数据分离建议(可选)

你可以将 leftSlidesrightSlides 提取到单独的 JSON 文件中,便于维护和国际化:

json 复制代码
// slides.js
export const leftSlides = [
    { title: 'Flying eagle', description: 'in the sunset', bgColor: '#FFB866' },
    ...
]

并在组件中导入:

js 复制代码
import { leftSlides, rightSlides } from '@/data/slides'

📁 常量定义 + 组件路由

constants/index.js 添加组件预览常量:

js 复制代码
{
        id: 26,
        title: 'Double Vertical Slider',
        image: 'https://50projects50days.com/img/projects-img/26-double-vertical-slider.png',
        link: 'DoubleVerticalSlider',
    },

router/index.js 中添加路由选项:

js 复制代码
{
        path: '/DoubleVerticalSlider',
        name: 'DoubleVerticalSlider',
        component: () => import('@/projects/DoubleVerticalSlider.vue'),
    },


🏁 总结

Vue 3 和 TailwindCSS 的全屏垂直轮播组件不仅实现了左右联动的滑动效果,还展示了如何通过响应式数据驱动 UI 变化。

适合用于需要高视觉表现力的网页场景,如企业主页、产品介绍页、摄影作品展示等。

你可以进一步扩展此组件的功能包括:

  • ✅ 自动播放(定时切换)
  • ✅ 支持键盘上下键切换
  • ✅ 添加分页指示器(圆点或数字)
  • ✅ 支持触摸滑动(移动端适配)
  • ✅ 将组件封装为 <AppCarousel /> 可复用组件

👉 下一篇,我们将完成ToastNotification组件,一个非常有趣的气泡消息通知。🚀

感谢阅读,欢迎点赞、收藏和分享 😊

相关推荐
知识分享小能手5 小时前
微信小程序入门学习教程,从入门到精通,微信小程序常用API(上)——知识点详解 + 案例实战(4)
前端·javascript·学习·微信小程序·小程序·html5·微信开放平台
清灵xmf5 小时前
CSS field-sizing 让表单「活」起来
前端·css·field-sizing
文火冰糖的硅基工坊5 小时前
[光学原理与应用-480]:《国产检测设备对比表》
前端·人工智能·系统架构·制造·半导体·产业链
excel5 小时前
Qiankun 子应用生命周期及使用场景解析
前端
weixin_446260856 小时前
Django - 让开发变得简单高效的Web框架
前端·数据库·django
蓝莓味的口香糖6 小时前
【JS】什么是单例模式
开发语言·javascript·单例模式
ObjectX前端实验室7 小时前
【react18原理探究实践】异步可中断 & 时间分片
前端·react.js
SoaringHeart7 小时前
Flutter进阶:自定义一个 json 转 model 工具
前端·flutter·dart
努力打怪升级7 小时前
Rocky Linux 8 远程管理配置指南(宿主机 VNC + KVM 虚拟机 VNC)
前端·chrome
brzhang7 小时前
AI Agent 干不好活,不是它笨,告诉你一个残忍的现实,是你给他的工具太难用了
前端·后端·架构