多条件联动筛选场景下如何跟踪状态实现汽车列表动态过滤?
实现思路
1. 状态拆分(核心前提)
首先纠正一个容易踩的误区:不要直接修改存储全量汽车的carJson,一旦覆盖原始数据,取消筛选或者切换筛选条件的时候无法回滚数据,必须单独留存一份不可修改的全量源数据。需要拆分的状态如下:
- 不可修改的全量源数据:单独存储原始全量汽车数据,永远不做修改,作为所有筛选的数据源。如果原始结构是对象格式,过滤时可以用
Object.values(carJson)转成数组处理。 - 选中的筛选条件:用对象存储三个维度的选中值,未选中的字段设为
null,示例结构:{ body_type: null, car_year: null, car_make: null } - 最终展示的车辆列表:单独存储过滤后的结果,用来渲染页面车辆列表
- 各筛选项的可选值:用对象存储三个维度的下拉可选值,动态更新
2. 核心联动计算逻辑
只要筛选条件发生变更,就按以下规则重新计算:
- 计算每个筛选项的可选值:计算某筛选项的可选值时,仅用另外两个筛选项的已选值过滤全量数据,对过滤结果的对应字段去重,就是该筛选项的可选值。
用需求中的场景验证逻辑正确性:- 已选
body_type: 'SUV',另外两个筛选项为空:- 计算
body_type可选值:用另外两个空条件过滤全量数据,去重后还是全量车身类型,符合需求里"body_type保持全量方便修改"的要求 - 计算
car_year可选值:用body_type: 'SUV'过滤全量数据,去重年份得到[2020,2021],符合示例结果 - 计算
car_make可选值:用body_type: 'SUV'过滤全量数据,去重品牌得到['Volvo','Jeep']
- 计算
- 后续再选
car_year: 2021:- 计算
body_type可选值:仅用car_year: 2021过滤全量数据,去重车身类型,仍然保持全量逻辑 - 计算
car_make可选值:用body_type: 'SUV' + car_year: 2021过滤全量数据,去重品牌得到['Volvo'],符合需求
- 计算
- 取消
body_type选中,仅保留car_year:2021:- 计算
body_type可选值:仅用car_year:2021过滤全量数据,去重车身类型得到该年份下的所有车身类型,符合需求3的要求
- 计算
- 已选
- 计算最终展示的车辆列表:用所有已选的三个筛选条件同时过滤全量数据,得到的结果就是当前要展示的车辆列表
3. 代码实现示例(React 场景)
// 初始全量数据,永远不修改 const FULL_CAR_DATA = Object.values(原始carJson); // 工具函数:数组去重 const getUniqueValues = (arr, key) => [...new Set(arr.map(item => item.attrs[key]))]; // 工具函数:按条件过滤 const filterCars = (cars, filters) => { return cars.filter(car => { return Object.entries(filters).every(([key, value]) => { return value === null ? true : car.attrs[key] === value; }) }) } function CarFilter() { const [selectedFilters, setSelectedFilters] = useState({ body_type: null, car_year: null, car_make: null }); const [filterOptions, setFilterOptions] = useState({ body_type: [], car_year: [], car_make: [] }); const [filteredCars, setFilteredCars] = useState([]); // 筛选变更时重新计算 useEffect(() => { // 分别计算三个筛选项的可选值 const newOptions = { body_type: getUniqueValues(filterCars(FULL_CAR_DATA, { ...selectedFilters, body_type: null }), 'body_type'), car_year: getUniqueValues(filterCars(FULL_CAR_DATA, { ...selectedFilters, car_year: null }), 'car_year'), car_make: getUniqueValues(filterCars(FULL_CAR_DATA, { ...selectedFilters, car_make: null }), 'car_make') }; setFilterOptions(newOptions); // 计算最终过滤后的车辆列表 setFilteredCars(filterCars(FULL_CAR_DATA, selectedFilters)); }, [selectedFilters]); // 筛选变更处理函数 const handleFilterChange = (key, value) => { setSelectedFilters(prev => ({ ...prev, [key]: value })); } // 后续渲染下拉选项和车辆列表即可 }
4. 优化提示
如果全量数据量很大(上万条),可以用useMemo缓存计算结果,避免重复计算导致的性能问题。
内容的提问来源于stack exchange,提问作者rnd om
相关产品推荐
相关产品推荐

