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

225 天前
 devzhaoyou

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

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

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

你这个场景只能说明每次触发更新生成了大量的 vdom ,《重新绘制所有子组件》可不一定,得看新旧 vdom diff 的结果
okakuyang
225 天前
多写写就习惯了,本质上是操作 dom 的方法那么多,改成操作数据减轻心智负担。
devzhaoyou
225 天前
感谢各位,感觉小脑袋瓜又疯狂的在长脑细胞
devzhaoyou
225 天前
@ChefIsAwesome 感谢,学到了
devzhaoyou
225 天前
@zerodli 其实也有疑惑是不是 vue 也是这样,感谢反馈
mipawn
225 天前
这个 map 里的 if 判断这块。再单独抽一个组件做这个事情,是可以做到性能优化的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1038698

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX