写一个记录增减列表的函数方法

57 阅读4分钟

为啥会写这么个星号玩意

在开发中遇到一个场景,在给一个数据编辑时需要绑定其他数据,这种在一般情况下是去由前端传一整个list过去由后端做处理(后端来个先删后插)即可,但是这边出现一个奇怪的场景,可绑定的其他数据可能达到24万条,所以就得前端来记录一下哪些数据被处理过,将被处理过的数据传过去。起初,我以为只是每一次对操作后数据做一个push,然后将这个操作后的数据传给后端即可,但是后端老哥对我又提出新的期望。什么意思呢?就是如果我先添加一个id为1的数据的绑定,再删除一条id为1的数据,这个表格不需要记录这条操作,以此类推,其实就是需要我们搞一个对一个id唯一的数据保存他的最后一次操作记录即可

原型图如下(俺自己画的,能看就行,不是搞产品的)

Cover.png 添加时选择另一个表的数据数据进行添加,选中后带出到编辑中,带出后可以自由编辑字段3,也可以在编辑页批量删除数据,只在点击抽屉底部保存时才与后端做交互,现在我们可以来拆解一下如何实现后端对前端的要求

实现步骤

拆解为三个需要记录的操作,分别为新增,编辑,删除,使用optionType属性记录,删除和新增都可能出现一次添加多条的场景,而编辑只会出现一次添加一条的场景

先来一个记录增删改查的操作

const RecordTableOperations = () => {
        //记录列表
        let recordList = [];
        //记录新增数据
        const addRecordList = (list) => {
          recordList = [
            ...recordList,
            ...list.map((item) => {
              return {
                ...item,
                optionType: "add",
              };
            }),
          ];
        };
        //记录删除数据
        const delRecordList = (list) => {
          recordList = [
            ...recordList,
            ...list.map((item) => {
              return {
                ...item,
                optionType: "del",
              };
            }),
          ];
        };
        //记录编辑数据
        const editRecordList = (obj) => {
          recordList = [
            ...recordList,
            {...obj, optionType: "edit",}
          ];
        };
        //获取当前记录列表数据
        const getRecordList = () => {
          return recordList;
        };

        return [getRecordList, addRecordList, delRecordList, editRecordList];
      };

设想一下 场景1,如果每个操作的id不同,那么每次的增删改,都只会保存当前的记录,即上面的方法已经够用了 再看看场景2,即有在记录列表中有相同id,应当如何操作呢?

  1. 先删除再新增,此时保存状态应该为edit,因为可能出现字段3不相同的情况
  2. 先新增再删除,此时应该将此条id的数据完全从记录列表中剔除
  3. 先新增再编辑,此时保存状态应该为add,因为在编辑表格中的操作并未与后端做交互
  4. 先编辑再删除, 此时保存状态应该为del,因为在编辑表格中的操作并未与后端做交互
  5. i除非后端的返回的id有重复出现,否则在一次操作中最多出现两个id一样的数据保存进记录数组,而将其做数据处理后就会在前端只留下不同id的数据

所以需要添加一个处理数据的函数和改动之前的三个方法

const RecordTableOperations = () => {
        //记录列表
        let recordList = [];

        const changeRecordList = (list) => {
          //让_list中只存在id唯一的数据
          let _recordList = recordList.filter(
            (item) => !list.map((ele) => ele.id).includes(item.id)
          );
          let _list = [..._recordList, ...list];
          let _list_ = _list.map((item) => {
            return {
              ...item,
              typeArr: [],
            };
          });
          //将两个数据拼接后给typeArr加数据,typeArr长度为1或2
          let _recordList_ = [...recordList, ...list];
          for (let i = 0; i < _list_.length; i++) {
            for (let j = 0; j < _recordList_.length; j++) {
              if (_list_[i].id === _recordList_[j].id) {
                _list_[i].typeArr.push(_recordList_[j].optionTYpe);
              }
            }
          }
          for (let i = 0; i < _list_.length; i++) {
            if (_list_[i].typeArr.length === 1) {
              _list_[i].optionTYpe = _list_[i].typeArr[0];
            }
            if (_list_[i].typeArr.length === 2) {
              if (
                _list_[i].typeArr[0] === "del" &&
                _list_[i].typeArr[1] === "add"
              ) {
                _list_[i].optionTYpe = "edit";
              }
              if (
                _list_[i].typeArr[0] === "add" &&
                _list_[i].typeArr[1] === "edit"
              ) {
                _list_[i].optionTYpe = "add";
              }
              if (
                _list_[i].typeArr[0] === "add" &&
                _list_[i].typeArr[1] === "del"
              ) {
                _list_[i].optionTYpe = null;
              }
              if (
                _list_[i].typeArr[0] === "edit" &&
                _list_[i].typeArr[1] === "del"
              ) {
                _list_[i].optionTYpe = "del";
              }
            }
          }
          recordList = _list_
            .map((item) => {
              let obj = item;
              delete obj.typeArr;
              return {
                ...obj,
              };
            })
            .filter((item) => item.optionTYpe);
        };
        //记录新增数据
        const addRecordList = (list) => {
          let _recordList = [
            ...list.map((item) => {
              return {
                ...item,
                optionTYpe: "add",
              };
            }),
          ];
          changeRecordList(_recordList);
        };
        //记录删除数据
        const delRecordList = (list) => {
          let _recordList = [
            ...list.map((item) => {
              return {
                ...item,
                optionTYpe: "del",
              };
            }),
          ];
          changeRecordList(_recordList);
        };
        //记录编辑数据
        const editRecordList = (obj) => {
          let _recordList = [{ ...obj, optionTYpe: "edit" }];
          changeRecordList(_recordList);
        };
        //获取当前记录列表数据
        const getRecordList = () => {
          return recordList;
        };

        return [getRecordList, addRecordList, delRecordList, editRecordList];
      };

执行结果

      addRecordList([{ id: 1, text: "1" }]); 
      delRecordList([{ id: 3, text: "1" }]); 
      editRecordList({ id: 1, text: "2" });
      console.log(getRecordList());
      
      //getRecordList结果如下
      [
        {
            "id": 3,
            "text": "1",
            "optionTYpe": "del"
        },
        {
            "id": 1,
            "text": "2",
            "optionTYpe": "add"
        }
      ]

前端操作结束

可能有观看的小伙伴会问为啥不直接传整个list而是传操作记录的数组,因为数据量大啊,产品设计不单独弄个页面去操作,得用一个保存来保存自身信息和绑定字段,所以搞了这么个星号玩意儿,喵的!!!掀桌子,不会干产品,他可以回去搬砖嘛,这不妥妥害人吗(小声抱怨“狗头”)