MST

星途 面试题库

面试题:React复杂列表排序与过滤的架构设计

假设有一个大型的React项目,其中涉及到复杂的列表数据展示,列表数据来自多个API接口,且数据量庞大。要求实现多种排序(如根据不同业务规则动态切换排序方式)和过滤(支持多条件组合过滤)功能。请设计一个合理的架构,包括数据管理、组件设计、性能优化等方面,并详细阐述你的设计思路。
47.0万 热度难度
前端开发React

知识考点

AI 面试

面试题答案

一键面试

数据管理

  1. 状态管理库:选用Redux或Mobx进行状态管理。以Redux为例,它可以将整个应用的状态存储在单一的store中,便于集中管理。
    • 创建不同的slice来管理列表数据、排序规则、过滤条件等状态。例如,listSlice管理列表数据,sortSlice管理排序规则,filterSlice管理过滤条件。
    • 利用Redux Toolkit简化状态管理逻辑,如使用createSlice方法快速创建slice并生成相应的action和reducer。
  2. 数据获取:使用axios等HTTP库来调用多个API接口。可以采用async/awaitredux - thunk等中间件来处理异步操作。
    • 创建一个apiService模块,封装所有API调用逻辑。例如:
    import axios from 'axios';
    
    const baseUrl = 'your - base - url';
    
    export const fetchListData = async () => {
        try {
            const response = await axios.get(`${baseUrl}/list - data`);
            return response.data;
        } catch (error) {
            console.error('Error fetching list data:', error);
            throw error;
        }
    };
    
    • 在Redux的thunk action中调用这些API函数,将获取到的数据存入store。例如:
    import { createAsyncThunk } from '@reduxjs/toolkit';
    import { fetchListData } from './apiService';
    
    export const getListData = createAsyncThunk(
        'list/getListData',
        async () => {
            const data = await fetchListData();
            return data;
        }
    );
    

组件设计

  1. 列表组件
    • 设计一个ListComponent,接收来自store的列表数据作为props。使用map方法遍历列表数据并渲染每个列表项。
    • 例如:
    import React from'react';
    import { useSelector } from'react-redux';
    
    const ListComponent = () => {
        const listData = useSelector((state) => state.list.listData);
    
        return (
            <ul>
                {listData.map((item) => (
                    <li key={item.id}>{item.name}</li>
                ))}
            </ul>
        );
    };
    
    export default ListComponent;
    
  2. 排序组件
    • 创建一个SortComponent,提供不同排序方式的选择按钮。当用户点击按钮时,dispatch相应的action更新store中的排序规则。
    • 例如:
    import React from'react';
    import { useDispatch } from'react-redux';
    import { setSortRule } from './sortSlice';
    
    const SortComponent = () => {
        const dispatch = useDispatch();
    
        const handleSort = (sortRule) => {
            dispatch(setSortRule(sortRule));
        };
    
        return (
            <div>
                <button onClick={() => handleSort('asc - by - name')}>Sort Asc by Name</button>
                <button onClick={() => handleSort('desc - by - age')}>Sort Desc by Age</button>
            </div>
        );
    };
    
    export default SortComponent;
    
  3. 过滤组件
    • 设计FilterComponent,提供多个过滤条件的输入框或选择框。用户操作时,dispatch action更新store中的过滤条件。
    • 例如:
    import React from'react';
    import { useDispatch } from'react-redux';
    import { setFilterCondition } from './filterSlice';
    
    const FilterComponent = () => {
        const dispatch = useDispatch();
        const handleFilter = (e) => {
            const { name, value } = e.target;
            dispatch(setFilterCondition({ [name]: value }));
        };
    
        return (
            <div>
                <input type="text" name="nameFilter" onChange={handleFilter} placeholder="Filter by name" />
                <select name="statusFilter" onChange={handleFilter}>
                    <option value="active">Active</option>
                    <option value="inactive">Inactive</option>
                </select>
            </div>
        );
    };
    
    export default FilterComponent;
    

性能优化

  1. 虚拟列表:由于数据量庞大,使用虚拟列表库如react - virtualizedreact - window。这些库只会渲染当前可见区域的列表项,大大减少DOM渲染数量,提升性能。
    • 例如,使用react - virtualizedList组件:
    import React from'react';
    import { List } from'react - virtualized';
    import { useSelector } from'react-redux';
    
    const VirtualListComponent = () => {
        const listData = useSelector((state) => state.list.listData);
    
        const rowRenderer = ({ index, key, style }) => {
            const item = listData[index];
            return (
                <div key={key} style={style}>
                    {item.name}
                </div>
            );
        };
    
        return (
            <List
                height={400}
                rowCount={listData.length}
                rowHeight={50}
                rowRenderer={rowRenderer}
                width={300}
            />
        );
    };
    
    export default VirtualListComponent;
    
  2. Memoization
    • 使用React.memo包裹纯函数组件,防止不必要的重新渲染。例如,ListComponentSortComponentFilterComponent如果是纯函数组件,可以用React.memo包裹。
    • 对于计算量较大的函数,如根据排序和过滤规则处理列表数据,可以使用useMemo钩子。例如,在ListComponent中:
    import React from'react';
    import { useSelector, useMemo } from'react-redux';
    
    const ListComponent = () => {
        const listData = useSelector((state) => state.list.listData);
        const sortRule = useSelector((state) => state.sort.sortRule);
        const filterCondition = useSelector((state) => state.filter.filterCondition);
    
        const filteredAndSortedData = useMemo(() => {
            // 根据过滤条件和排序规则处理listData
            let filteredData = listData;
            if (filterCondition.nameFilter) {
                filteredData = filteredData.filter((item) => item.name.includes(filterCondition.nameFilter));
            }
            if (sortRule === 'asc - by - name') {
                filteredData.sort((a, b) => a.name.localeCompare(b.name));
            } else if (sortRule === 'desc - by - age') {
                filteredData.sort((a, b) => b.age - a.age);
            }
            return filteredData;
        }, [listData, sortRule, filterCondition]);
    
        return (
            <ul>
                {filteredAndSortedData.map((item) => (
                    <li key={item.id}>{item.name}</li>
                ))}
            </ul>
        );
    };
    
    export default ListComponent;
    
  3. Debounce and Throttle:对于过滤组件中的输入框等频繁触发的事件,可以使用防抖(debounce)或节流(throttle)技术。例如,对于搜索框的输入事件,使用防抖可以减少不必要的API调用或状态更新。可以使用lodashdebounce函数:
    import React from'react';
    import { useDispatch } from'react-redux';
    import { setFilterCondition } from './filterSlice';
    import { debounce } from 'lodash';
    
    const FilterComponent = () => {
        const dispatch = useDispatch();
        const debouncedHandleFilter = debounce((e) => {
            const { name, value } = e.target;
            dispatch(setFilterCondition({ [name]: value }));
        }, 300);
    
        const handleFilter = (e) => {
            debouncedHandleFilter(e);
        };
    
        return (
            <div>
                <input type="text" name="nameFilter" onChange={handleFilter} placeholder="Filter by name" />
                <select name="statusFilter" onChange={handleFilter}>
                    <option value="active">Active</option>
                    <option value="inactive">Inactive</option>
                </select>
            </div>
        );
    };
    
    export default FilterComponent;
    

设计思路:通过合理的状态管理,将数据、排序和过滤状态集中管理,便于维护和更新。组件设计上,将不同功能模块拆分为独立组件,提高代码的可维护性和复用性。性能优化方面,针对数据量大的问题采用虚拟列表,通过Memoization减少不必要的渲染,利用防抖和节流处理频繁触发事件,从而提升整个应用的性能和用户体验。