V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
elone
V2EX  ›  React

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

  •  1
     
  •   elone · 2017-03-26 23:06:00 +08:00 · 8118 次点击
    这是一个创建于 2580 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我现在在做一个题库项目,一个题库可以对应数道题目,数量多时应该可以是几千上万道题。 现在的搭配是 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 条回复    2017-03-27 15:19:29 +08:00
    vizards
        1
    vizards  
       2017-03-27 01:06:59 +08:00 via iPhone
    既然用了 antd 为嘛不考虑直接用 antd 的表格啊
    elone
        2
    elone  
    OP
       2017-03-27 06:39:39 +08:00 via Android
    @vizards 有在用啊
    ghostheaven
        3
    ghostheaven  
       2017-03-27 07:13:45 +08:00 via Android
    如果数据量不是非常大的话建一个 id->data 的哈希表,每次添加删除的时候都查询一下
    des
        4
    des  
       2017-03-27 07:42:47 +08:00 via Android
    1 、换成对象,用 id 做 key
    2 、手工指定对象本身为 key , indexOf 这个对象是没问题的。

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

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

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


    手机码字,不知道是否有表达清晰,😂
    elone
        8
    elone  
    OP
       2017-03-27 12:24:21 +08:00
    我现在这样做:
    ```
    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
       2017-03-27 12:35:42 +08:00
    至于 删除就这样:
    this.props.setItembankRelatedQuestions(array.xorBy(this.props.questions,this.state.selectedRows,'id')
    otakustay
        10
    otakustay  
       2017-03-27 13:48:51 +08:00
    首先我不太相信你的数据量真的会很大,万条以内做 filter 根据 id 找一下不会消耗什么时间的
    其次删除用 filter ,添加用 concat ,这还是比较简单的
    不建议同时维护一个 id 的 Set ,这种同步的代价比较大,除非你设计出一个 SortedSet 的结构来
    elone
        11
    elone  
    OP
       2017-03-27 14:12:43 +08:00 via Android
    @otakustay 谢谢你。所以说我可能想太多了
    otakustay
        12
    otakustay  
       2017-03-27 14:18:58 +08:00
    @elone 我做过万条数据排序的优化,大概知道这个耗时的量级,删除和插入复杂度比排序低得多,完全没问题的
    sunber
        13
    sunber  
       2017-03-27 15:19:29 +08:00
    如果 react 列表所需要的 key 使用的是服务器生成的,那么可以在请求添加成功时,服务器返回新增的 id ,应该不会和当前 store 里面的重复了吧
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1118 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 23:01 · PVG 07:01 · LAX 16:01 · JFK 19:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.