50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | FAQ Collapse(问题解答折叠面板)
📅 我们继续 50 个小项目挑战!—— FAQCollapse
组件
仓库地址:https://github.com/SunACong/50-vue-projects
项目预览地址:https://50-vue-projects.vercel.app/
使用 Vue 3 的 Composition API 和 <script setup>
语法结合 TailwindCSS 构建一个带有动画效果的常见问题(FAQ)折叠面板组件。该组件支持点击展开/收起,并为每个问答项添加了优雅的过渡动画。
🎯 组件目标
- 展示一组常见问题(FAQ)。
- 每个问题可以独立展开与收起。
- 使用 TailwindCSS 快速构建美观的 UI 界面。
- 添加平滑的动画过渡效果提升用户体验。
⚙️ 技术实现点
技术点 | 描述 |
---|---|
Vue 3 Composition API (<script setup> ) | 使用响应式变量管理组件状态 |
v-for 循环渲染 | 动态生成多个 FAQ 条目 |
v-if 控制内容显示 | 判断当前条目是否展开 |
@click 事件绑定 | 控制展开/收起动作 |
Transition 组件 | 添加进入和离开动画 |
TailwindCSS 布局与样式 | 快速构建现代 UI |
🧱 组件实现
模板结构 <template>
<template><div class="m-12 flex flex-col items-center justify-center gap-8 text-white"><h3 class="font-mono text-2xl font-bold">Frequently Asked Questions</h3><divv-for="(item, index) in FQList":key="item.id"class="w-2xl overflow-hidden rounded-2xl bg-gray-500 p-8"><div class="flex cursor-pointer items-start justify-between"><div class="text-xl font-bold">{{ item.question }}</div><div v-if="item.isOpen" class="text-2xl font-bold" @click="currentCollapse(index)">-</div><div v-else class="text-2xl font-bold" @click="currentCollapse(index)">+</div></div><Transitionenter-active-class="transition duration-500 ease-in-out"enter-from-class="opacity-0 -translate-y-2"enter-to-class="opacity-100 translate-y-0"leave-active-class="transition duration-200 ease-in"leave-from-class="opacity-100 translate-y-0"leave-to-class="opacity-0 -translate-y-2"><div v-if="item.isOpen" class="mt-4 text-xl font-bold">{{ item.answer }}</div></Transition></div></div>
</template>
脚本逻辑 <script setup>
<script setup>
import { ref } from 'vue'const current = ref(0)const currentCollapse = (index) => {FQList.value[index].isOpen = !FQList.value[index].isOpen
}const FQList = ref([{id: 1,question: 'What is Vue.js?',answer: 'Vue.js is a progressive JavaScript framework for building user interfaces. It is designed to be incrementally adoptable, and can easily scale between a simple static site and a complex single-page application.',isOpen: false,},{id: 2,question: 'What are the main features of Vue.js?',answer: 'Vue.js provides reactive data binding, component-based architecture, virtual DOM rendering, and powerful tooling like Vue Router and Vuex for state management.',isOpen: false,},{id: 3,question: 'How does Vue 3 differ from Vue 2?',answer: 'Vue 3 introduces a new Composition API, improved TypeScript support, better performance with the reactivity system, and smaller bundle size compared to Vue 2.',isOpen: false,},{id: 4,question: 'Is Vue.js suitable for large-scale applications?',answer: 'Yes, Vue.js is suitable for both small projects and large-scale enterprise applications due to its modular structure, ecosystem tools, and scalability.',isOpen: false,},
])
</script>
🔍 重点效果实现
✅ 折叠面板切换逻辑
通过 currentCollapse(index)
方法控制每个条目的 isOpen
状态:
const currentCollapse = (index) => {FQList.value[index].isOpen = !FQList.value[index].isOpen
}
这样就能实现点击“+”或“-”按钮时切换对应面板的展开/收起状态。
🎭 过渡动画实现
我们使用 Vue 的 <Transition>
组件并自定义类名来实现动画:
<Transitionenter-active-class="transition duration-500 ease-in-out"enter-from-class="opacity-0 -translate-y-2"enter-to-class="opacity-100 translate-y-0"leave-active-class="transition duration-200 ease-in"leave-from-class="opacity-100 translate-y-0"leave-to-class="opacity-0 -translate-y-2"><div v-if="item.isOpen" class="mt-4 text-xl font-bold">{{ item.answer }}</div>
</Transition>
enter-*
类控制元素进入时的动画。leave-*
类控制元素离开时的动画。duration-500
、ease-in-out
等是 Tailwind 提供的动画持续时间和缓动函数类。
🎨 TailwindCSS 样式重点讲解
类名 | 作用 |
---|---|
m-12 | 外边距为 3rem |
flex , flex-col | 弹性布局并设置为纵向排列 |
items-center , justify-center | 内容居中对齐 |
gap-8 | 子元素之间间距为 2rem |
text-white | 设置文字颜色为白色 |
font-mono | 使用等宽字体 |
rounded-2xl | 圆角大小为 1rem |
bg-gray-500 | 设置背景颜色为灰色 |
p-8 | 内边距为 2rem |
cursor-pointer | 鼠标悬停时变为手型 |
overflow-hidden | 隐藏超出容器的内容,用于动画流畅展示 |
text-xl , text-2xl | 不同层级的文字大小 |
font-bold | 加粗字体 |
mt-4 | 上边距为 1rem |
这些 Tailwind 工具类帮助我们快速完成了一个现代、响应式的 FAQ 页面设计。
📁 常量定义 + 组件路由
constants/index.js
添加组件预览常量:
{id: 12,title: 'FAQ Collapse',image: 'https://50projects50days.com/img/projects-img/12-faq-collapse.png',link: 'FAQCollapse',},
router/index.js
中添加路由选项:
{path: '/FAQCollapse',name: 'FAQCollapse',component: () => import('@/projects/FAQCollapse.vue'),
},
🏁 总结
这个 FAQ 折叠面板组件虽然功能简单,但涵盖了 Vue 3 的响应式系统、条件渲染、事件处理以及 <Transition>
动画组件的使用,同时借助 TailwindCSS 快速实现了美观的 UI 设计。
👉 下一篇,我们将完成RandomChoicePicker
组件,一个现代化的折叠Q&A面板!🚀