如何在React.js中实现卡片组件的分类筛选功能?
React 实现工具卡片的分类筛选功能
核心思路
- 用
useState维护当前选中的分类标识,初始值设为代表“全部”的特殊值(比如'ALL') - 结合你已有的搜索关键词筛选逻辑,同时叠加分类筛选条件:当选中“全部”时不做分类过滤,否则只保留
category匹配选中分类的卡片 - 渲染分类选择控件时,默认添加“全部”选项,再遍历你的分类数组生成其他选项
完整代码示例
import { useState } from 'react'; // 模拟你的分类数据 const categories = [ { id: 1, name: '开发工具' }, { id: 2, name: '设计工具' }, { id: 3, name: '协作工具' } ]; // 模拟你的工具卡片数据 const tools = [ { id: 1, title: 'VS Code', description: '代码编辑器', category: '开发工具' }, { id: 2, title: 'Figma', description: 'UI设计工具', category: '设计工具' }, { id: 3, title: 'GitHub', description: '代码托管平台', category: '开发工具' }, { id: 4, title: 'Slack', description: '团队协作工具', category: '协作工具' } ]; function ToolCard({ tool }) { return ( <div style={{ border: '1px solid #eee', padding: '16px', margin: '8px', borderRadius: '4px' }}> <h3>{tool.title}</h3> <p>{tool.description}</p> <span style={{ fontSize: '12px', color: '#666' }}>{tool.category}</span> </div> ); } function ToolGallery() { // 分类筛选状态,初始为全部 const [selectedCategory, setSelectedCategory] = useState('ALL'); // 已有的搜索关键词状态 const [searchQuery, setSearchQuery] = useState(''); // 组合搜索+分类的过滤逻辑 const filteredTools = tools.filter(tool => { // 搜索匹配:标题或描述包含关键词(不区分大小写) const matchesSearch = tool.title.toLowerCase().includes(searchQuery.toLowerCase()) || tool.description.toLowerCase().includes(searchQuery.toLowerCase()); // 分类匹配:选中全部则通过,否则匹配分类名称 const matchesCategory = selectedCategory === 'ALL' || tool.category === selectedCategory; return matchesSearch && matchesCategory; }); return ( <div style={{ maxWidth: '1200px', margin: '0 auto', padding: '20px' }}> {/* 搜索框(你已有的组件) */} <input type="text" placeholder="搜索工具..." value={searchQuery} onChange={(e) => setSearchQuery(e.target.value)} style={{ padding: '8px', width: '300px', marginBottom: '16px' }} /> {/* 分类选择下拉框 */} <select value={selectedCategory} onChange={(e) => setSelectedCategory(e.target.value)} style={{ padding: '8px', marginBottom: '16px' }} > <option value="ALL">全部</option> {categories.map(category => ( <option key={category.id} value={category.name}> {category.name} </option> ))} </select> {/* 工具卡片列表 */} <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(250px, 1fr))', gap: '16px' }}> {filteredTools.map(tool => ( <ToolCard key={tool.id} tool={tool} /> ))} </div> </div> ); } export default ToolGallery;
实用建议
- 如果分类数量较多,下拉框可以换成标签按钮组(比如用
button元素,选中时高亮),交互更直观 - 把筛选逻辑抽成自定义Hook(比如
useFilteredTools),方便在多个组件中复用,也让主组件更简洁:function useFilteredTools(tools, searchQuery, selectedCategory) { return useMemo(() => { return tools.filter(tool => { const matchesSearch = tool.title.toLowerCase().includes(searchQuery.toLowerCase()) || tool.description.toLowerCase().includes(searchQuery.toLowerCase()); const matchesCategory = selectedCategory === 'ALL' || tool.category === selectedCategory; return matchesSearch && matchesCategory; }); }, [tools, searchQuery, selectedCategory]); } - 当工具数据量较大时,用
useMemo缓存过滤后的结果,避免每次渲染都重复执行过滤逻辑,提升性能 - 如果分类的
id和name是一一对应的,也可以用分类id作为选中值(比如把selectedCategory初始设为0代表全部),这样更严谨,避免分类名称重复的问题
内容的提问来源于stack exchange,提问作者Muhammad Hassan Saeed
相关产品推荐
相关产品推荐

