50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | FeedbackUiDesign(评价反馈组件)

📅 我们继续 50 个小项目挑战!—— FeedbackUiDesign组件

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

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

在这里插入图片描述


使用 Vue 3<script setup> 语法结合 Tailwind CSS 来构建一个美观且交互性强的用户满意度评分组件。这个组件允许用户通过点击表情图标来选择他们的满意度等级,并在提交后显示感谢信息,非常适合用于收集客户反馈、产品评价或服务评分。

让我们开始吧!🚀


📝 应用目标

  • 使用 Vue 3 Composition API 管理组件状态
  • 实现可点击的评分选项,支持视觉反馈(悬停、选中效果)
  • 展示提交前后的不同界面状态
  • 利用 Tailwind CSS 快速构建现代化、响应式的 UI
  • 提供流畅的用户体验和动画效果

🔧 技术实现点

技术点描述
Vue 3 <script setup>使用 ref 定义响应式数据和事件处理函数
v-for 循环渲染动态生成评分选项
v-if / v-else 条件渲染根据是否提交切换显示不同的面板
@click 事件监听处理用户点击评分和提交按钮
:class 动态绑定根据选中状态应用不同的样式
transition-all duration-200添加平滑的过渡动画
active:scale-98点击时的轻微缩小效果,增强触觉反馈

🖌️ 组件实现

🎨 模板结构 <template>

<template>
    <div class="flex min-h-screen items-center justify-center bg-gray-100 p-4 font-sans">
        <!-- 主面板容器 (提交前) -->
        <div
            class="w-full max-w-md rounded-lg bg-white p-8 text-center shadow-md"
            v-if="!isSubmitted">
            <strong class="leading-relaxed text-gray-800">
                How satisfied are you with our
                <br />
                customer support performance?
            </strong>

            <!-- 评分选项容器 -->
            <div class="my-8 flex justify-center">
                <div
                    v-for="rating in ratings"
                    :key="rating.id"
                    @click="selectRating(rating.value)"
                    :class="[
                        'flex cursor-pointer flex-col items-center rounded-md p-5 transition-all duration-200',
                        selectedRating === rating.value
                            ? 'scale-110 bg-white shadow-lg'
                            : 'hover:bg-gray-50',
                    ]">
                    <img :src="rating.imgUrl" :alt="rating.label" class="mb-3 h-10 w-10" />
                    <small class="text-gray-600">{{ rating.label }}</small>
                </div>
            </div>

            <!-- 提交按钮 -->
            <button
                @click="submitFeedback"
                class="rounded-md bg-gray-800 px-8 py-3 text-white transition-all duration-200 hover:bg-gray-700 active:scale-98">
                Send Review
            </button>
        </div>

        <!-- 提交后的感谢面板 -->
        <div class="w-full max-w-md rounded-lg bg-white p-8 text-center shadow-md" v-else>
            <i class="fas fa-heart mb-4 text-4xl text-red-500"></i>
            <strong class="mb-1 block text-xl text-gray-800">Thank You!</strong>
            <strong class="mb-2 text-gray-700">Feedback: {{ selectedRating }}</strong>
            <p class="text-sm text-gray-500">
                We'll use your feedback to improve our customer support
            </p>
        </div>
    </div>
</template>

模板部分清晰地分为两个主要状态:

  1. 提交前状态 (v-if="!isSubmitted")

    • 标题:使用 <strong> 标签显示询问用户满意度的问题。
    • 评分选项:使用 v-for 遍历 ratings 数组生成三个可点击的选项。每个选项包含一个表情图标和标签文字。@click 事件绑定到 selectRating 函数。
    • 动态样式:class 绑定根据 selectedRating 是否等于当前评分的 value 来决定应用哪种样式。选中时放大 (scale-110) 并添加阴影 (shadow-lg);未选中时悬停 (hover:bg-gray-50) 有轻微背景色变化。
    • 提交按钮:点击后触发 submitFeedback 函数。
  2. 提交后状态 (v-else)

    • 显示一个感谢界面,包含一个爱心图标(使用 Font Awesome)、感谢语、用户选择的反馈值以及一段说明文字。

💻 脚本逻辑 <script setup>

<script setup>
    import { ref } from 'vue'

    // 响应式状态
    const selectedRating = ref('Satisfied') // 默认选中Satisfied
    const isSubmitted = ref(false)

    // 评分选项数据
    const ratings = ref([
        {
            id: 1,
            imgUrl: 'https://img.icons8.com/external-neu-royyan-wijaya/64/000000/external-emoji-neumojis-smiley-neu-royyan-wijaya-17.png',
            label: 'Unhappy',
            value: 'Unhappy',
        },
        {
            id: 2,
            imgUrl: 'https://img.icons8.com/external-neu-royyan-wijaya/64/000000/external-emoji-neumojis-smiley-neu-royyan-wijaya-3.png',
            label: 'Neutral',
            value: 'Neutral',
        },
        {
            id: 3,
            imgUrl: 'https://img.icons8.com/external-neu-royyan-wijaya/64/000000/external-emoji-neumojis-smiley-neu-royyan-wijaya-30.png',
            label: 'Satisfied',
            value: 'Satisfied',
        },
    ])

    // 选择评分
    const selectRating = (rating) => {
        selectedRating.value = rating
    }

    // 提交反馈
    const submitFeedback = () => {
        isSubmitted.value = true
    }
</script>

脚本部分定义了组件的核心逻辑:

  • 状态定义selectedRating 存储用户选择的评分值,isSubmitted 控制面板的显示状态。
  • 数据定义ratings 数组包含了三个评分选项的详细信息,包括图标 URL、显示标签和内部值。
  • 事件处理
    • selectRating(rating):当用户点击某个评分选项时,将 selectedRating 更新为该选项的 value
    • submitFeedback():当用户点击“Send Review”按钮时,将 isSubmitted 设置为 true,从而切换到感谢面板。

🎨 Tailwind CSS 样式重点

类名作用
flex启用 Flexbox 布局
min-h-screen最小高度为视口高度,确保内容垂直居中
items-center / justify-centerFlex 项目在主轴和交叉轴上居中
bg-gray-100浅灰色背景
p-4内边距
font-sans无衬线字体
w-full max-w-md宽度占满,但最大宽度限制为 md (28rem)
rounded-lg中等圆角
bg-white白色背景
p-8较大的内边距
text-center文本居中
shadow-md中等阴影
leading-relaxed较宽松的行高
text-gray-800 / text-gray-600 / text-gray-500 / text-gray-700不同深浅的灰色文字
my-8上下外边距
justify-centerFlex 容器内项目居中对齐
cursor-pointer鼠标指针变为手型
flex-colFlex 方向为垂直
p-5内边距
transition-all duration-200所有属性变化在 200ms 内平滑过渡
scale-110放大到 110%
bg-white shadow-lg选中时的背景和更强阴影
hover:bg-gray-50悬停时的浅灰色背景
mb-3下边距
h-10 w-10图标固定大小
rounded-md按钮圆角
bg-gray-800 / bg-gray-700按钮背景色及悬停色
px-8 py-3按钮内边距
text-white白色文字
hover:bg-gray-700悬停时按钮颜色变浅
active:scale-98按下时轻微缩小
text-4xl大号文字(爱心图标)
text-red-500红色文字
block块级元素
text-xl大号文字

📁 常量定义 + 组件路由

{
        id: 43,
        title: 'FeedbackUiDesign',
        image: 'https://50projects50days.com/img/projects-img/43-feedback-ui-design.png',
        link: 'FeedbackUiDesign',
    },

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

{
        path: '/FeedbackUiDesign',
        name: 'FeedbackUiDesign',
        component: () => import('@/projects/FeedbackUiDesign.vue'),
    },

🏁 总结

在这篇教程中,我们成功创建了一个直观、美观且交互性良好的用户反馈评分组件。

想要让你的反馈组件更加强大?考虑以下扩展功能:

  • 提交到后端:在 submitFeedback 函数中添加 fetchaxios 请求,将 selectedRating 发送到服务器保存。
  • 输入框收集详细反馈:在提交前,增加一个 <textarea> 让用户输入更详细的反馈意见。
  • 动画效果:为面板切换或图标添加更丰富的动画(例如使用 vue-transition)。
  • 自定义图标:使用本地 SVG 图标或不同的图标库替换现有的表情图片。
  • 评分重置:在感谢面板添加一个“再次评分”按钮,允许用户重新选择。
  • 本地存储:使用 localStorage 记住用户之前的评分(如果需要)。

👉 下一篇,我们将完成RangeSlider组件,一个可以自定义的范围滑块组件。🚀

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值