React JS自定义筛选面板开发求助:多维度筛选实现思路
React 多维度按钮筛选面板实现思路
1. 定义筛选状态结构
用useState统一管理所有筛选维度的状态,把每个维度的选中值存到一个对象里,方便后续统一处理:
import { useState, useMemo } from 'react'; const ShirtFilter = () => { // 初始化筛选条件,默认无选中(可根据需求设默认值) const [filters, setFilters] = useState({ priceRange: '', // 可选值:'0-100', '100-200', '200+' hasPattern: '', // 可选值:'yes', 'no' brand: '' // 可选值:'Nike', 'Adidas', 'Uniqlo'等 }); // 原始衬衫数据示例 const shirtData = [ { id: 1, name: '条纹衬衫', price: 99, hasPattern: true, brand: 'Uniqlo' }, { id: 2, name: '纯色T恤', price: 159, hasPattern: false, brand: 'Nike' }, { id: 3, name: '印花衬衫', price: 249, hasPattern: true, brand: 'Adidas' } ];
2. 实现筛选条件更新函数
写一个通用的状态更新函数,根据点击的按钮所属维度,精准更新对应状态值:
const handleFilterChange = (filterType, value) => { setFilters(prev => ({ ...prev, [filterType]: value })); };
3. 渲染筛选按钮组
每个维度做独立按钮组,给选中状态的按钮加active类(需自行编写CSS样式标记选中态):
return ( <div className="filter-panel"> {/* 价格筛选组 */} <div className="filter-group"> <h3>价格区间</h3> <button className={filters.priceRange === '0-100' ? 'active' : ''} onClick={() => handleFilterChange('priceRange', '0-100')} > 0-100元 </button> <button className={filters.priceRange === '100-200' ? 'active' : ''} onClick={() => handleFilterChange('priceRange', '100-200')} > 100-200元 </button> <button className={filters.priceRange === '200+' ? 'active' : ''} onClick={() => handleFilterChange('priceRange', '200+')} > 200元以上 </button> <button className={filters.priceRange === '' ? 'active' : ''} onClick={() => handleFilterChange('priceRange', '')} > 全部 </button> </div> {/* 有无图案筛选组 */} <div className="filter-group"> <h3>有无图案</h3> <button className={filters.hasPattern === 'yes' ? 'active' : ''} onClick={() => handleFilterChange('hasPattern', 'yes')} > 有图案 </button> <button className={filters.hasPattern === 'no' ? 'active' : ''} onClick={() => handleFilterChange('hasPattern', 'no')} > 无图案 </button> <button className={filters.hasPattern === '' ? 'active' : ''} onClick={() => handleFilterChange('hasPattern', '')} > 全部 </button> </div> {/* 品牌筛选组 */} <div className="filter-group"> <h3>品牌</h3> <button className={filters.brand === 'Uniqlo' ? 'active' : ''} onClick={() => handleFilterChange('brand', 'Uniqlo')} > Uniqlo </button> <button className={filters.brand === 'Nike' ? 'active' : ''} onClick={() => handleFilterChange('brand', 'Nike')} > Nike </button> <button className={filters.brand === 'Adidas' ? 'active' : ''} onClick={() => handleFilterChange('brand', 'Adidas')} > Adidas </button> <button className={filters.brand === '' ? 'active' : ''} onClick={() => handleFilterChange('brand', '')} > 全部 </button> </div>
4. 实现核心筛选逻辑
用useMemo缓存筛选结果,避免每次渲染重复计算,仅当筛选条件或原始数据变化时重新过滤:
{/* 筛选结果展示 */} <div className="filtered-results"> <h3>筛选结果</h3> {filteredShirts.map(shirt => ( <div key={shirt.id} className="shirt-item"> <p>{shirt.name}</p> <p>价格:{shirt.price}元</p> <p>图案:{shirt.hasPattern ? '有' : '无'}</p> <p>品牌:{shirt.brand}</p> </div> ))} </div> </div> ); }; export default ShirtFilter;
补充筛选函数的实现(放在组件内部return之前):
const filteredShirts = useMemo(() => { return shirtData.filter(shirt => { // 价格匹配逻辑 const matchesPrice = !filters.priceRange || ( (filters.priceRange === '0-100' && shirt.price <= 100) || (filters.priceRange === '100-200' && shirt.price > 100 && shirt.price <= 200) || (filters.priceRange === '200+' && shirt.price > 200) ); // 图案匹配逻辑 const matchesPattern = !filters.hasPattern || ( (filters.hasPattern === 'yes' && shirt.hasPattern) || (filters.hasPattern === 'no' && !shirt.hasPattern) ); // 品牌匹配逻辑 const matchesBrand = !filters.brand || shirt.brand === filters.brand; // 所有条件满足才保留 return matchesPrice && matchesPattern && matchesBrand; }); }, [filters, shirtData]);
5. 可选优化点
- 若需多选维度(比如同时选多个品牌),把对应状态改成数组(如
brand: []),点击按钮时切换数组内的选中值,筛选逻辑改为shirt.brand.includes(选中品牌)或数组为空时全选。 - 把每个筛选维度封装成独立组件(如
PriceFilter.jsx),通过props传递选中值和更新函数,提升代码模块化程度。 - 添加重置按钮,一键清空所有筛选条件:
onClick={() => setFilters({priceRange: '', hasPattern: '', brand: ''})}
内容的提问来源于stack exchange,提问作者JonD
相关产品推荐
相关产品推荐

