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

React 中添加、删除、变更子组件疑问

  •  
  •   devzhaoyou · 2024-05-08 12:07:03 +08:00 · 2193 次点击
    这是一个创建于 485 天前的主题,其中的信息可能已经有所发展或是发生改变。

    React 做一个画图组件,在 CanvaEditor 添加各种 Shape 图形

    <CanvaEditor>
        <Rect/>
        <Circle/>
        ....
    </CanvaEditor>
    

    如果要动态的添加删除 Shape ,就得创建一个保存 shape 属性的列表,然后再遍历渲染

    const (ShapeList)  = useState({type, width, heigth ....})
    
    <CanvaEditor>
         ShapeList.map(
            (shape) => {
                if(shapre.type === 'rect')
                    return <<Rect/>
                else if(shape.type === 'circle')
                    return <<Circle/>
            }
        )
    </CanvaEditor>
    
    
    // 动态添加图形, 触发 CanvaEditor 重新渲染
    const AddShape = (shape) => {
        ShapeList.push(shape)
    }
    

    疑问:

    1. React 中要添加和删除子组件,都是必须通过有的数据列表转换一道吗?有什么其他操作方法?
    2. 如果上面保存 Shape 的列表 ShapeList 有成千上万个,一旦变更里面的一个 React 都要重新遍历 map ,重新绘制所有子组件吗,这不很浪费吗?
    16 条回复    2024-05-09 00:17:11 +08:00
    horizon
        1
    horizon  
       2024-05-08 12:44:43 +08:00
    加个 key ,可以不更新
    nulIptr
        2
    nulIptr  
       2024-05-08 12:48:23 +08:00
    1.如果不在列表中可以简单的使用条件语句渲染,比如{show&&<div></div>}
    2.map 出来的组件只是虚拟 dom ,通过传入相同的 key 可以保持对应节点不重新渲染(条件比较复杂,大致就是没有任何状态变化),或者你自己可以用 useMemo 优化,
    devzhaoyou
        3
    devzhaoyou  
    OP
       2024-05-08 13:02:41 +08:00
    所以 React 里类似这种场景都是要有数据作为驱动的?数据变,渲染的 UI 也变

    如果是 js 写类似的场景, 写一个 canvaEditor.add(new Shape) 完事了,React 里还要经过数据列表中转一下,个人感觉这不是退步吗?
    codehz
        4
    codehz  
       2024-05-08 13:10:40 +08:00
    如果你这个没有任何层级结构的话
    那确实没有任何优势,react 那种玩法在有复杂层级结构的情况下效果还不错(因为比较只需要考虑一层
    beginor
        5
    beginor  
       2024-05-08 13:27:38 +08:00 via Android
    可以通过 ref 拿到 canvas 元素自己想干啥都行,react 确实是数据/状态驱动的
    ChefIsAwesome
        7
    ChefIsAwesome  
       2024-05-08 13:47:02 +08:00
    首先理解 mvc 框架的应用场景:当一个数据对应多个视图的时候,改一次数据,多个视图自动更新。
    你这是一对一的,用 mvc 当然是多绕了一个圈子。
    HackerJax
        8
    HackerJax  
       2024-05-08 13:47:09 +08:00
    canvaEditor.add(new Shape) 跟 ShapeList.push(shape) 有啥区别?
    zerodli
        9
    zerodli  
       2024-05-08 13:58:08 +08:00
    这是虚拟 dom 这一类前端框架的共同特点,体现的是一个易用性和数据视图的一致性,另外一种以 svelte 、solid 为主的无虚拟 dom 的前端框架,具备编译功能,减轻一些客户端的性能损耗
    maolon
        10
    maolon  
       2024-05-08 14:02:55 +08:00 via Android
    对 你这个要求直接拿 ref 搞是正确做法,实际上 react 对上 canvas 场景基本都是各种 anti-pattern 的 ref 乱飞搞定的
    lisongeee
        11
    lisongeee  
       2024-05-08 14:08:16 +08:00
    数据变会导致 hook 函数重新运行生成新的 vdom ,然后新旧 vdom 对比后再去更新真实 dom 节点

    > 如果上面保存 Shape 的列表 ShapeList 有成千上万个,一旦变更里面的一个 React 都要重新遍历 map ,重新绘制所有子组件吗,这不很浪费吗?

    你这个场景只能说明每次触发更新生成了大量的 vdom ,《重新绘制所有子组件》可不一定,得看新旧 vdom diff 的结果
    okakuyang
        12
    okakuyang  
       2024-05-08 15:04:11 +08:00 via iPhone
    多写写就习惯了,本质上是操作 dom 的方法那么多,改成操作数据减轻心智负担。
    devzhaoyou
        13
    devzhaoyou  
    OP
       2024-05-08 16:58:03 +08:00
    感谢各位,感觉小脑袋瓜又疯狂的在长脑细胞
    devzhaoyou
        14
    devzhaoyou  
    OP
       2024-05-08 16:59:44 +08:00
    @ChefIsAwesome 感谢,学到了
    devzhaoyou
        15
    devzhaoyou  
    OP
       2024-05-08 17:01:36 +08:00
    @zerodli 其实也有疑惑是不是 vue 也是这样,感谢反馈
    mipawn
        16
    mipawn  
       2024-05-09 00:17:11 +08:00
    这个 map 里的 if 判断这块。再单独抽一个组件做这个事情,是可以做到性能优化的
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2265 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 16:07 · PVG 00:07 · LAX 09:07 · JFK 12:07
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.