一个组件比较多的页面,即使更新一个小组件,也必须走一遍整个页面的 render ,怎么处理呢?

2021-08-05 10:23:38 +08:00
 sillydaddy
现在有一个 react 构造的页面,页面上有很多元素。整个页面是根据一个数据文档(data_document),自顶向下构造的构造的。
自顶向下就是说,使用 data_document.dataA 构造组件 A,data_document.dataB 构造组件 B 。。然后使用 dataA 里面的子 dataAA,构造组件 A 里的子组件 AA 。

这里有个问题是,当我操作了页面里面很小的一个组件,从而修改了这个组件对应的 data 时,我需要触发页面的根组件 render(),将整个页面构造一遍。我的思考是,这些页面里的所有组件,都是由 data_document 里的某些 data 完全决定的,它们显示状态变了,就意味着 data_document 变了,反过来也是。所有的组件都是没有额外的状态 state 的。所以想要操作某个组件改变它的状态,就要改变 data_document 的某些 data,将新 data 作为 props 再传递给它。由于整个页面的构建是自顶向下构造的,想要改变传递给某个子组件的 props,就需要跑页面根组件的 render()。

虽然 render 只是重新构造整个虚拟 dom 树而不是真实 dom 树,但如果组件多的话,跑一遍也很费时间。对于这种情况,有什么好的思路吗?
( 这里要注意的是,由于多个组件可能会用同一个数据,所以每次的修改都要即时反馈到 data_document 中,这样的话让被修改的组件只更新自己的 state 就行不通了。)
2823 次点击
所在节点    React
24 条回复
shakukansp
2021-08-05 10:32:46 +08:00
办法就是不用 react……
kop1989
2021-08-05 10:33:08 +08:00
所以你要去学习 react Context 的使用。
binaryify
2021-08-05 10:36:15 +08:00
人生苦短,我用 Vue
kop1989
2021-08-05 10:38:09 +08:00
换而言之,如果一个 dom 的数据与逻辑必须强依赖其“父亲”,那其实他就不是一个独立的“组件”,其渲染与数据处理的动作必然和其他兄弟组件有耦合关系(前提是你的组件规划合理)。所以你也应该接受带者父亲整体重绘。
kop1989
2021-08-05 10:46:29 +08:00
而传统的针对性操作子 dom 组件的方式,其实是你通过人脑处理了兄弟组件的耦合关系。
而 react 等工程化库的目的,就是将组件间充分解耦。

解耦的结果必然会出现冗余与浪费。而当前的互联网带宽与客户端性能也禁得起这样的浪费。
sillydaddy
2021-08-05 10:48:21 +08:00
@kop1989
不太明白。组件的一个作用是可以复用。这里我看不出父组件与子组件有什么“强依赖”的关系。父组件只是把数据传递给子组件啊。比如父组件 A 下面有子组件 A1 、A2 、A3,子组件 A1 变了,修改 A1 对应的数据 data1,这时 A2,A3 数据根本没有变化,也没有依赖 A1,但是也要重绘。
kop1989
2021-08-05 10:51:44 +08:00
@sillydaddy #6 所以你的解决方式有两种。

1 、将 A1 剥离 A 。
2 、通过全局变量(比如 context )来控制 A1 所需要的数据。

如果这两者都不能,那就其实说明 A1 与 A,以及 A2A3 其实有耦合关系。只不过未见得是数据上的。
huai
2021-08-05 10:53:30 +08:00
@sillydaddy 大多时候不会存在啥性能问题,需要的时候 可以看看

React.memo

PureComponent

shouldcomponentupdate
binaryify
2021-08-05 11:01:09 +08:00
用 shouldcomponentupdate 比较数据或者 mobx 自动判断
XTTX
2021-08-05 11:03:08 +08:00
现在都在用 useEffect 替代 cmd,purecomponet 。useCallback 对应 function useMemo 对应运算结果。 建议 op 去学 react hooks, 因为它已经是主流了
dashixiong1990
2021-08-05 11:03:42 +08:00
组件 React.memo
数据 immer
XTTX
2021-08-05 11:07:19 +08:00
react hooks 里 包括 useContext, 可以带入 reducer. 你描述的问题就是 react 以前的传统问题,hooks 可以解决。useContext 大部分情况下替代 redux 。你设计好的话,prop drilling 不会是问题。
DICK23
2021-08-05 11:09:59 +08:00
render 消耗其实不太大,大部分组件哪怕重新走了一遍 render 流程,实际性能影响微乎其微。
实在不行就手写 memo 的比较函数,手动指定依赖值
sherryqueen
2021-08-05 11:13:21 +08:00
memo 比较函数.
sweetcola
2021-08-05 11:23:01 +08:00
可以把数据拆分成几个 reducer(slice) 放进 Redux 里,把 state 下沉到子组件。
ykrank
2021-08-05 11:23:10 +08:00
你需要的是 mobx 之类吧
chenpingan
2021-08-05 11:39:03 +08:00
react.memo 或者 useMemo 都可以解决这个问题
KouShuiYu
2021-08-05 11:50:51 +08:00
改用 vue 就不会有这个问题,
charlie21
2021-08-05 14:26:33 +08:00
很典型的问题
HAYWAEL
2021-08-05 15:12:13 +08:00

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

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

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

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

© 2021 V2EX