📅 我们继续 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>
<div
v-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>
<Transition
enter-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>
组件并自定义类名来实现动画:
<Transition
enter-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面板!🚀