当前位置: 首页 > news >正文

50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | LiveUserFilter(实时用户过滤组件)

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

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

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

在这里插入图片描述


🔍 使用 Vue 3 和 Tailwind CSS 构建实时用户搜索过滤器

欢迎来到本篇教程!今天我们将使用 Vue 3<script setup> 语法结合 Tailwind CSS 来创建一个功能强大且视觉美观的实时用户搜索过滤组件。这个组件能够从远程 API 获取用户数据,并根据用户输入的关键词实时过滤并展示结果,非常适合用于构建用户目录、联系人列表或任何需要搜索功能的界面。

让我们开始吧!🚀


📝 应用目标

  • 使用 Vue 3 Composition API 管理异步数据获取与状态
  • 实现基于姓名和/或位置的实时用户搜索过滤
  • 展示加载状态和无结果状态
  • 使用 Tailwind CSS 快速构建现代化的 UI 组件
  • 优化用户体验,提供流畅的搜索反馈

🔧 技术实现点

技术点描述
Vue 3 <script setup>使用 ref, onMounted, computed 管理状态、生命周期和计算属性
async/await异步获取远程用户数据
computed 属性响应式地过滤用户列表
v-model 双向绑定绑定搜索输入框的值
v-for 渲环渲染动态生成用户列表项
v-if 条件渲染根据状态显示加载中、用户列表或无结果提示
Tailwind CSS快速实现响应式布局与视觉样式

📚 常量和路由定义

虽然本示例是一个独立的功能组件,但理解其核心配置和数据流对于维护和扩展至关重要:

常量/配置值/说明
API_URLhttps://randomuser.me/api?results=50 - 用于获取随机用户数据的公共 API
resultsCount50 - 一次请求获取的用户数量
searchTerm (响应式)存储用户输入的搜索关键词
users (响应式)存储从 API 获取的原始用户数据数组
filteredUsers (计算属性)根据 searchTerm 过滤后的用户列表
isLoading (响应式)控制加载状态显示的布尔值

💡 提示:在实际项目中,这些配置(如 API 地址)可以定义为常量或从环境变量中读取,便于统一管理和环境切换。


🖌️ 组件实现

🎨 模板结构 <template>

<template><divclass="flex min-h-screen items-center justify-center overflow-hidden bg-gray-100 font-sans"><div class="w-72 overflow-hidden rounded-lg bg-white shadow-md"><!-- 头部搜索区域 --><div class="bg-blue-600 p-6 text-white"><h4 class="mb-1 text-xl font-bold">Live User Filter</h4><small class="opacity-80">Search by name and/or location</small><inputv-model="searchTerm"@input="filterUsers"class="mt-3 w-full rounded-full bg-blue-800/50 px-4 py-2 text-sm text-white focus:outline-none"placeholder="Search" /></div><!-- 用户列表区域 --><ul class="max-h-96 overflow-y-auto"><!-- 加载状态 --><li v-if="isLoading" class="p-6 text-center"><h3>Loading...</h3></li><!-- 过滤后的用户列表 --><liv-for="user in filteredUsers":key="user.login.uuid"class="flex items-center border-b border-gray-100 p-4"><img:src="user.picture.large":alt="`${user.name.first} ${user.name.last}`"class="h-12 w-12 rounded-full object-cover" /><div class="ml-3"><h4 class="font-medium text-gray-900">{{ user.name.first }} {{ user.name.last }}</h4><p class="text-xs text-gray-500">{{ user.location.city }}, {{ user.location.country }}</p></div></li><!-- 无结果状态 --><liv-if="!isLoading && filteredUsers.length === 0"class="p-6 text-center text-gray-500">No users found</li></ul></div></div>
</template>

模板部分清晰地分为两个主要区域:

  1. 头部搜索区域:包含标题、说明和一个搜索输入框。输入框使用 v-model 绑定到 searchTerm,并监听 @input 事件(尽管实际过滤由 computed 属性驱动)。
  2. 用户列表区域:一个可滚动的列表,根据 isLoadingfilteredUsers 的状态动态显示:
    • isLoadingtrue 时显示“Loading…”。
    • 否则,使用 v-for 遍历 filteredUsers 显示用户头像、姓名和位置。
    • filteredUsers 为空且非加载状态时,显示“No users found”。

💻 脚本逻辑 <script setup>

<script setup>import { ref, onMounted, computed } from 'vue'// 响应式状态const users = ref([])const searchTerm = ref('')const isLoading = ref(true)// 获取用户数据const fetchUsers = async () => {try {isLoading.value = trueconst response = await fetch('https://randomuser.me/api?results=50')const data = await response.json()users.value = data.results} catch (error) {console.error('Error fetching users:', error)} finally {isLoading.value = false}}// 过滤用户数据const filteredUsers = computed(() => {if (!searchTerm.value) return users.valueconst term = searchTerm.value.toLowerCase()return users.value.filter((user) => {const fullName = `${user.name.first} ${user.name.last}`.toLowerCase()const location = `${user.location.city} ${user.location.country}`.toLowerCase()return fullName.includes(term) || location.includes(term)})})// 组件挂载时获取数据onMounted(() => {fetchUsers()})// 暴露给模板的方法const filterUsers = () => {} // 仅为了模板中绑定,实际过滤通过computed完成
</script>

🎉 关键功能解析

状态定义

users 存储用户数据,searchTerm 存储搜索关键词,isLoading 控制加载状态。

数据获取

fetchUsers 函数使用 fetch API 异步获取 50 个随机用户数据,并在成功或失败后更新 isLoading 状态。

数据过滤

filteredUsers 是一个 computed 属性,它会自动响应 searchTermusers 的变化。当 searchTerm 为空时返回所有用户;否则,将用户姓名和位置转换为小写,并检查是否包含搜索关键词(也转为小写),返回匹配的用户数组。

生命周期

onMounted 钩子确保组件挂载后立即调用 fetchUsers 获取数据。

方法占位

filterUsers 函数虽然在模板中被绑定,但实际过滤逻辑由 computed 属性 filteredUsers 完成,因此该函数为空。v-model 的更新足以触发 computed 的重新计算。


🎨 Tailwind CSS 样式重点

类名作用
flex启用 Flexbox 布局
min-h-screen设置最小高度为视口高度,确保内容居中
items-center / justify-center在主轴和交叉轴上居中对齐
overflow-hidden隐藏溢出内容
bg-gray-100设置浅灰色背景
font-sans使用无衬线字体
w-72设置固定宽度(18rem)
rounded-lg添加中等圆角
bg-white白色背景
shadow-md添加中等阴影,提升立体感
bg-blue-600搜索区域深蓝色背景
p-6内边距
text-white白色文字
mb-1下边距
text-xl / text-sm字体大小
font-bold / font-medium字体粗细
opacity-80降低不透明度
mt-3上边距
rounded-full完全圆形(圆角)
bg-blue-800/50深蓝色背景,50% 透明度(使用 Tailwind CSS 新的透明度语法)
px-4 py-2水平/垂直内边距
focus:outline-none移除聚焦轮廓
max-h-96设置最大高度(24rem),创建滚动区域
overflow-y-autoY轴自动出现滚动条
border-b border-gray-100底部浅灰色边框,分隔列表项
p-4列表项内边距
flex items-center水平 Flex 布局,垂直居中
h-12 w-12头像固定大小
rounded-full头像圆形
object-cover图片填充容器并保持比例
ml-3左边距
text-gray-900 / text-gray-500文字颜色
text-xs小号文字

📁 常量定义 + 组件路由

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

{id: 42,title: 'LiveUserFilter',image: 'https://50projects50days.com/img/projects-img/42-live-user-filter.png',link: 'LiveUserFilter',},

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

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

🏁 总结

在这篇教程中,我们成功构建了一个功能完整、界面美观的实时用户搜索过滤组件。我们利用了 Vue 3 的响应式系统(特别是 computed 属性)来实现高效的过滤逻辑,并通过 Tailwind CSS 快速搭建了现代化的 UI。

想要让你的用户过滤器更加强大?试试这些扩展功能:

  • 防抖搜索:如果数据量巨大或 API 有调用限制,可以为搜索输入添加防抖(debounce)功能,避免过于频繁的计算或 API 调用。
  • 高级筛选:除了搜索框,添加下拉菜单或复选框进行更精确的筛选(如按国家、性别等)。
  • 分页:当用户数据量非常大时,实现分页功能。
  • 缓存机制:缓存已获取的数据,避免重复请求。
  • 错误处理 UI:除了 console.error,在界面上显示友好的错误提示。
  • 键盘导航:支持使用键盘上下键在用户列表中导航。

👉 下一篇,我们将完成FeedbackUiDesign组件,实现了一个好玩儿的好评反馈组件。🚀

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

http://www.lryc.cn/news/605493.html

相关文章:

  • ensp安全策略实验
  • 【工具】NVM完全指南:Node.js版本管理工具的安装与使用详解
  • 嵌入式仿真教学的革新力量:深圳航天科技创新研究院引领高效学习新时代
  • 【n8n】如何跟着AI学习n8n【03】:HTTPRequest节点、Webhook节点、SMTP节点、mysql节点
  • 从“碎片化”到“完美重组”:IP报文的分片艺术
  • mysql笔记02:DML插入、更新、删除数据
  • 【读书笔记】Design Patterns (1994)✅
  • 微软发布Microsoft Sentinel数据湖国际版
  • JVM之【Java虚拟机概述】
  • Python实现调整矩阵维度: view
  • 【13】大恒相机SDK C#开发 —— Fom1中实时处理的8个图像 实时显示在Form2界面的 pictureBox中
  • 磁盘坏道检测工具在美国服务器硬件维护中的使用规范
  • MVS相机+YOLO检测方法
  • 【03】大恒相机SDK C#开发 —— 回调采集图像,关闭相机
  • Java WEB技术-序列化和反序列化认识(SpringBoot的Jackson序列化行为?如何打破序列化过程的驼峰规则?如何解决学序列化循环引用问题?)
  • 学习笔记《区块链技术与应用》第三天 网络 难度
  • 详解分布式数据库缓存技术:高性能数据访问的基石
  • 如何在 macOS 上使用 dnsmasq 搭建本地 DNS 缓存/转发
  • 深度解析:基于Python构建的闲鱼自动化营销与信息发送机器人
  • IO流专题
  • linux运维学习第十三周
  • Linux 服务器性能优化:性能监控,系统性能调优,进程优先级,内核升级全解析
  • 前端框架Vue3(二)——Vue3核心语法之OptionsAPI与CompositionAPI与setup
  • AWS云安全审计终极实战指南:构建自动化安全防线
  • 数字化应急预案:构筑现代安全防线
  • Web3:在 VSCode 中使用 Vue 前端与已部署的 Solidity 智能合约进行交互
  • 从渠道渗透到圈层渗透:开源链动2+1模式、AI智能名片与S2B2C商城小程序的协同创新路径研究
  • 【09】大恒相机SDK C#开发 ——库函数 IntPtr ConvertToRGB24详细解释 及 示例
  • 【JEECG】JVxeTable表格拖拽排序功能
  • 动态规划Day5学习心得