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

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

  •  
  •   devzhaoyou · 233 天前 · 1839 次点击
    这是一个创建于 233 天前的主题,其中的信息可能已经有所发展或是发生改变。

    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  
       233 天前
    加个 key ,可以不更新
    nulIptr
        2
    nulIptr  
       233 天前
    1.如果不在列表中可以简单的使用条件语句渲染,比如{show&&<div></div>}
    2.map 出来的组件只是虚拟 dom ,通过传入相同的 key 可以保持对应节点不重新渲染(条件比较复杂,大致就是没有任何状态变化),或者你自己可以用 useMemo 优化,
    devzhaoyou
        3
    devzhaoyou  
    OP
       233 天前
    所以 React 里类似这种场景都是要有数据作为驱动的?数据变,渲染的 UI 也变

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

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

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