如何在ReactJS中使用Material UI芯片选择器筛选卡片?
ReactJS + Material UI 芯片选择器实现标签筛选卡片功能
1. 基础准备与数据结构
首先定义卡片数据,每个卡片包含用于筛选的标签数组:
const cardData = [ { id: 1, title: "React 入门教程", tags: ["react", "frontend", "beginner"] }, { id: 2, title: "Material UI 组件详解", tags: ["mui", "frontend", "ui"] }, { id: 3, title: "Node.js 后端实战", tags: ["nodejs", "backend", "api"] }, { id: 4, title: "全栈项目实战", tags: ["react", "nodejs", "fullstack"] }, ]; // 提取所有唯一标签作为选择器选项 const allTags = [...new Set(cardData.flatMap(card => card.tags))];
2. 实现芯片选择器
使用Material UI的Select组件开启multiple模式,通过renderValue将选中标签渲染为芯片:
import { useState } from "react"; import { Select, MenuItem, Chip, Box, Typography, Card, CardContent } from "@mui/material"; function TagFilteredCards() { const [selectedTags, setSelectedTags] = useState([]); // 处理标签选择变更 const handleTagChange = (event) => { setSelectedTags(event.target.value); }; // 自定义选中标签的渲染样式 const renderSelectedTags = (selected) => ( <Box sx={{ display: "flex", flexWrap: "wrap", gap: 0.5 }}> {selected.map((tag) => ( <Chip key={tag} label={tag} /> ))} </Box> );
3. 实现筛选逻辑
根据选中标签过滤卡片,提供两种常用逻辑:
- 任意匹配:卡片包含至少一个选中标签即显示
- 全匹配:卡片必须包含所有选中标签才显示
// 筛选卡片 - 任意匹配逻辑 const filteredCards = selectedTags.length === 0 ? cardData : cardData.filter(card => selectedTags.some(tag => card.tags.includes(tag)) ); // 若需要全匹配逻辑,替换为以下代码: // const filteredCards = selectedTags.length === 0 // ? cardData // : cardData.filter(card => // selectedTags.every(tag => card.tags.includes(tag)) // );
4. 渲染筛选结果
最后渲染选择器和筛选后的卡片列表:
return ( <Box sx={{ padding: 3, maxWidth: 800, margin: "0 auto" }}> <Typography variant="h6" gutterBottom> 选择标签筛选卡片 </Typography> <Select multiple value={selectedTags} onChange={handleTagChange} renderValue={renderSelectedTags} sx={{ width: "100%", marginBottom: 3 }} displayEmpty > {allTags.map((tag) => ( <MenuItem key={tag} value={tag}> {tag} </MenuItem> ))} </Select> <Box sx={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(250px, 1fr))", gap: 2 }}> {filteredCards.map((card) => ( <Card key={card.id}> <CardContent> <Typography variant="h6">{card.title}</Typography> <Box sx={{ marginTop: 1, display: "flex", flexWrap: "wrap", gap: 0.5 }}> {card.tags.map((tag) => ( <Chip key={tag} label={tag} size="small" /> ))} </Box> </CardContent> </Card> ))} </Box> </Box> ); } export default TagFilteredCards;
关键细节说明
renderValue属性用于自定义选中值的展示,这里直接渲染为Material UI芯片displayEmpty属性允许选择器在未选中任何标签时显示占位状态- 可根据业务需求切换
some(任意匹配)或every(全匹配)逻辑
内容的提问来源于stack exchange,提问作者Aman Shukla
相关产品推荐
相关产品推荐

