react 如何最好的实现对列表的增删操作? - V2EX
elone
V2EX    React

react 如何最好的实现对列表的增删操作?

  •  1
     
  •   elone Mar 26, 2017 8772 views
    This topic created in 3339 days ago, the information mentioned may be changed or developed.

    我现在在做一个题库项目,一个题库可以对应数道题目,数量多时应该可以是几千上万道题。 现在的搭配是 react+redux+antdesign 在设计这个后台管理系统。 但是有一点我想请教一下各位。 比如说,在为题库新添加题目时,是怎么样个流程比较合适,我有两个想法:

    一、

    1 、添加 /删除 题目,客户端发起一个请求,服务端处理完毕返回。

    2 、待返回后,客户端再发起一个请求,请求返回所有题目的新数据 ,以此新数据来更新客户端列表。

    二、

    1 、添加 /删除 题目,客户端发起一个请求,服务端处理完毕返回。

    2 、由客户端将新添加的数据插入(删除)到原数据中,以此起到更新数据的作用。

    第一种要发起两个请求才能完成一件事,第二种只要一个请求,但实现起来有点麻烦。

    麻烦就麻烦在于,如何插入,以及如何删除列表中指定的数据 。

    我本来是这样写的:

     handlerOk = (sourceData) => { if ( typeof(sourceData) !== "undefined") { //此处为一个 redux action this.props.setQuestions(this.props.questions.concat(sourceData)); } } this.props.questions 为原始数据 sourceData 为新添加的数据项 都为对象列表 [{id:1,name"test1"}, {id:2,name"test2"}, {id:3,name"test3"}, ] 

    以上代码确实可以在不请求服务器的情况下更新数据到原始数据中。但是有一个问题,就是插入的数据如果与原始数据项有重复项的时候,是会报错的,因为我采用 id 为 key ,而 key 在渲染时有重复是会报错的。 而如果要排除重复项,因为是对象列表, indexOf 似乎是无效的。只能一个一个遍历对比,感觉这样下来,如果数据量大的时候,应该相当费力。

    以前使用 jquery 时,直接操作 dom 虽然粗暴却很容易 。现在使用 react ,感觉不太适应。请各位指点一下,我的需求就是说: 一个展示 列表,有一个新增按钮,删除按钮,当新增时,可以把新添加的数据项更新到列表中,而不用发起请求刷新全部数据。

    13 replies    2017-03-27 15:19:29 +08:00
    vizards
        1
    vizards  
       Mar 27, 2017 via iPhone
    既然用了 antd 为嘛不考虑直接用 antd 的表格啊
    elone
        2
    elone  
    OP
       Mar 27, 2017 via Android
    @vizards 有在用啊
    ghostheaven
        3
    ghostheaven  
       Mar 27, 2017 via Android
    如果数据量不是非常大的话建一个 id->data 的哈希表,每次添加删除的时候都查询一下
    des
        4
    des  
       Mar 27, 2017 via Android
    1 、换成对象,用 id 做 key
    2 、手工指定对象本身为 key , indexOf 这个对象是没问题的。

    还有为什么会有重复的?你确定不是 bug ?
    ChefIsAwesome
        5
    ChefIsAwesome  
       Mar 27, 2017 via Android
    不懂你的问题。你添加了之后 id 怎么能重复的
    serco
        6
    serco  
       Mar 27, 2017
    问题的 id 是客户端生成的还是服务端,如果客户端生成,生成的时候就该生成一个 unique id 。如果是服务端生成的,又怎么会出现重复。

    你自己说的第一种方式,可以在步骤一就返回全部的新数据,完全没必要两次请求。
    但是你也说了数据可能会有很多,每次增删改查都返回全部数据显然并不合适。
    elone
        7
    elone  
    OP
       Mar 27, 2017 via Android
    id 为数据库的 id 。关于重复 id 的事情也许是我的设计问题吧。有一个列表 A ,展示已关联的题目,(比如此时有列表项{id:1}{id:2}),有一个新增按钮,点击后出现所有题目列表以待选择,选择后如上所说,将新选择的题目更新到列表 A 中,如果不幸还选择了 id 为 1 的选项,当返回给列表 A 时就会出现重复的问题了。

    不过这应该是我设计上的缺陷吧,应该在所有列表中禁用已关联的题目,使其不能选择。只不过似乎又要遍历才能对比出哪些题目已关联。


    手机码字,不知道是否有表达清晰,
    elone
        8
    elone  
    OP
       Mar 27, 2017
    我现在这样做:
    ```
    handlerOk = (sourceData) => {
    if ( typeof(sourceData) !== "undefined") {
    var newQ = this.props.questions.concat(sourceData);
    newQ = array.uniqBy(newQ,`id`);
    this.props.setItembankRelatedQuestions(newQ);
    }
    }
    ```
    以后再考虑性能问题吧。感觉现阶段有点想太多了。
    elone
        9
    elone  
    OP
       Mar 27, 2017
    至于 删除就这样:
    this.props.setItembankRelatedQuestions(array.xorBy(this.props.questions,this.state.selectedRows,'id')
    otakustay
        10
    otakustay  
       Mar 27, 2017
    首先我不太相信你的数据量真的会很大,万条以内做 filter 根据 id 找一下不会消耗什么时间的
    其次删除用 filter ,添加用 concat ,这还是比较简单的
    不建议同时维护一个 id 的 Set ,这种同步的代价比较大,除非你设计出一个 SortedSet 的结构来
    elone
        11
    elone  
    OP
       Mar 27, 2017 via Android
    @otakustay 谢谢你。所以说我可能想太多了
    otakustay
        12
    otakustay  
       Mar 27, 2017
    @elone 我做过万条数据排序的优化,大概知道这个耗时的量级,删除和插入复杂度比排序低得多,完全没问题的
    sunber
        13
    sunber  
       Mar 27, 2017
    如果 react 列表所需要的 key 使用的是服务器生成的,那么可以在请求添加成功时,服务器返回新增的 id ,应该不会和当前 store 里面的重复了吧
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86