IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    高性能分组列表设计-2

    Ashes Born\'s Blog发表于 2021-07-30 06:14:19
    love 0
    • 通过改变列表项位置更新分组关系
    • 要解决的问题
    • 分析
    • 实现

    通过改变列表项位置更新分组关系#

    要解决的问题#

    • 移动分组时,分组所有的子项都要移动,且保持相对位置和关系不变
    • 批量移动未分组列表项到分组内时,相对位置应不变
    • 已分组列表项移动出分组范围时应,应解除分组关系

    分析#

    当分组移动时,所有分组的子项都不变,首先需要搜索到分组内所有的子项。然后记录该子项在分组内的相对位置,以及在整体列表中的位置。 这样在移动时,方便进行计算。

    整体来讲,这个移动过程中的搜索部分将使用深度优先搜索的一种变种。移动后的排序,只需遵守搜索中分组和其子项的相对顺序遍历即可。

    分组子项搜索流程如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    if (!groupCache.includes(hasGroup)) {
    //组件的分组不在查询的分组内。弹出所有的分组缓存
    groupCache = [];
    return;
    } else {
    result.push(item); //组件的分组在分组缓存中

    if (hasGroup !== groupCache[groupCache.length - 1]) {
    // 如果组件的分组不在缓存的顶层
    const hasGroupCacheIndex = groupCache.indexOf(hasGroup);
    groupCache = groupCache.slice(0, hasGroupCacheIndex + 1);
    }
    if (compDatas[item].compCode === 'group') {
    // 组件本身是分组组件
    groupCache.push(item);
    }
    }

    列表项排序流程如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31

    /**
    * compDatas 所有的列表项{[code]:{ config: { [groupCode]:groupCode } } }
    * topLestSelectComps 和第一个要移动的列表项在同级的组件(处理批量移动的情况),数据结构与compDatas一致
    * nearLowBoundsGroup 将要移动列表项所在的分组的下界,数据结构与compDatas一致
    */
    if (isToplest) {
    //如果移动位置在插入区间的顶部,表明组件在最外层
    topLestSelectComps.forEach((item) => {

    result[item] = { newGroup: undefined, oldGroup: compDatas[item].config.groupCode };
    return (compDatas[item].config.groupCode = undefined);
    });

    return result;
    }
    if (nearLowBoundsGroup !== firstCompPrev) {
    //如果移动位置的下界的分组code不等于移动组件的code,则解除或更新分组关系
    topLestSelectComps.forEach((item) => {
    if (item !== nearLowBoundsGroup) {
    result[item] = { newGroup: nearLowBoundsGroup, oldGroup: compDatas[item].config.groupCode };
    compDatas[item].config.groupCode = nearLowBoundsGroup;
    } else {
    result[item] = { newGroup: compDatas[item].config.groupCode, oldGroup: compDatas[item].config.groupCode };
    }
    });
    return result;
    }
    return result;
    };

    实现#

    分组子项查询详细代码
            interface GroupConfigStruct {      groupItemCode: string[];    }    interface groupMapValueStruct {      //分组内组件相对于分组索引的偏移量      offsetNumer: number;      //分组的索引      currentIndex: number;    }    /**    *根据分组关系排序一维数组    *@param compCodes 所有组件的code    *@param compDatas 所有组件的数据    */    const sortListItem = (compCodes: string[], compDatas: JDV.State['compDatas']) => {      const groupCodeCache = new Map();      const result: string[] = [];      /**      *递归的回溯当前分组的前驱分组,更新前驱分组的长度偏移量      *@param groupCode 分组组件的code      *@param offsetNumber 分组长度的偏移量      */      const recursiveBacktracking = (groupCode: string, offsetNumber: number): null => {        const parentGroupCode = compDatas[groupCode].config.groupCode;        const belongGroup = groupCodeCache.get(groupCode) as groupMapValueStruct;        groupCodeCache.set(groupCode, {          //更新分组缓存,每此插入组件,偏移量+1          ...belongGroup,          offsetNumer: belongGroup.offsetNumer + 1,        });        if (parentGroupCode) {          // 如果分组有父分组,回溯一步          return recursiveBacktracking(parentGroupCode, offsetNumber + 1);        } else {          return null;        }      };      compCodes.forEach((item, index) => {        const group = compDatas[item].config.groupCode ? compDatas[item].config.groupCode : null;        if (compDatas[item].compCode === 'group') {          //如果组件是分组组件,将code推入分组缓冲内          groupCodeCache.set(item, { offsetNumer: 0, currentIndex: index });        }        if (group) {          //在分组内          if (groupCodeCache.has(group)) {            // 组件的分组在缓存中            const belongGroup = groupCodeCache.get(group) as groupMapValueStruct;            // 分组内组件插入的位置            const targetIndex = belongGroup.currentIndex + belongGroup.offsetNumer;            result.splice(targetIndex + 1, 0, item);            recursiveBacktracking(group, belongGroup.offsetNumer);          }        } else {          result.push(item);        }      });      return result;    };    export default sortListItem;      
    分组移动后排序详细代码
            /** * 组件排序时处理分组的逻辑。 * @param compCodes 所有组件的code * @param compDatas 所有组件的数据 * @param code 当前组件code * @param destination 目标位置 * @returns result {Result} 返回组件排序后的分组关系,用于分组关系变化后,处理分组的尺寸。 */export const groupResort = (  compCodes: string[],  selectedCompCodes: string[],  compDatas: JDV.State['compDatas'],  destination: number): Result => {  const isToplest = destination === 0;  const isBottomlest = destination + 1 === compCodes.length - 1;  const lowBounds = isBottomlest ? compCodes.length - 1 : destination + 1;  const interval = compCodes.slice(0, lowBounds); //插入区间  const intervalLastComp = compDatas[compCodes[lowBounds]];  const nearLowBoundsGroup = interval.find((item) => intervalLastComp && item === intervalLastComp.config.groupCode); //插入区间最下面的分组段  const firstCompPrev = compDatas[selectedCompCodes[0]] && compDatas[selectedCompCodes[0]].config.groupCode; // 第一个选中组件的分组  const topLestSelectComps = selectedCompCodes.filter((item) => compDatas[item].config.groupCode === firstCompPrev); // 和第一个选中在同级的所有选中组件  const result: Result = {};  if (isToplest) {    //如果移动位置在插入区间的顶部,表明组件在最外层    topLestSelectComps.forEach((item) => {      result[item] = { newGroup: undefined, oldGroup: compDatas[item].config.groupCode };      return (compDatas[item].config.groupCode = undefined);    });    return result;  }  if (nearLowBoundsGroup !== firstCompPrev) {    //如果移动位置的下界的分组code不等于移动组件的code,则解除或更新分组关系    topLestSelectComps.forEach((item) => {      if (item !== nearLowBoundsGroup) {        result[item] = { newGroup: nearLowBoundsGroup, oldGroup: compDatas[item].config.groupCode };        compDatas[item].config.groupCode = nearLowBoundsGroup;      } else {        result[item] = { newGroup: compDatas[item].config.groupCode, oldGroup: compDatas[item].config.groupCode };      }    });    return result;  }  return result;};      


沪ICP备19023445号-2号
友情链接