Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[react] 说说你对React的渲染原理的理解 #950

Open
haizhilin2013 opened this issue Jul 18, 2019 · 11 comments
Open

[react] 说说你对React的渲染原理的理解 #950

haizhilin2013 opened this issue Jul 18, 2019 · 11 comments
Labels
react react

Comments

@haizhilin2013
Copy link
Collaborator

[react] 说说你对React的渲染原理的理解

@haizhilin2013 haizhilin2013 added the react react label Jul 18, 2019
@chenchujuan
Copy link

自上而下的单向数据流

@UserRegistering
Copy link

这个问题我感觉可能描述的不全面,先讲一下我的描述吧:
1.单向数据流。React是一个MVVM框架,简单来说是在MVC的模式下在前端部分拆分出数据层和视图层。单向数据流指的是只能由数据层的变化去影响视图层的变化,而不能反过来(除非双向绑定)
2.数据驱动视图。我们无需关注页面的DOM,只需要关注数据即可
3.渲染过程,生命周期……
4.setState()大部分时候是异步执行的,提升性能。

@liuyingbin19222
Copy link

  • react通过diff 算法对照两次dom不同的部分进行渲染。

@hdugaojing
Copy link

感觉可以从以下几个方面回答:
1、元素渲染、更新(这块可以从JSX解析,diff算法来谈);
2、生命周期
3、props、state更新

@wjrhyw
Copy link

wjrhyw commented Apr 17, 2020

从一个完整的流程来说:首先编写的jsx会被转换执行返回node对象,node对象就可以理解为是虚拟dom,渲染时都会将老的虚拟dom和新的虚拟dom来进行比对,比对的过程中就涉及到了diff算法,只比较同一层的节点,节点tag不同,就不再比较,以新的节点为准,节点相同就比较key,key不同也会以新节点为准;之后就将最终的虚拟dom,再渲染在浏览器中;props,state的更新也会触发这一流程

@LiFeng007
Copy link

React整个渲染机制就是React会调用React.render()构建一颗DOM树
当state或props改变时,render()会被再次调用构建出另外一颗树,利用Diff算法与之前的树进行对比,找到需要更新的地方进行更新并渲染到页面上,实现按需更新减少对真实DOM的操作,实现性能优化
个人理解这个问题重点在React.render() 和 Diff算法上

@pureZjr
Copy link

pureZjr commented Mar 6, 2021

1.render函数,调用React.createElement接收type,options,childrens,生成虚拟dom。
2.通过改变state或props触发更新。
3.对比新旧虚拟dom,diff算法,深度优先,将实际需要改变的反应到真实dom。

@ouuz
Copy link

ouuz commented Mar 15, 2021

感觉可以通过VDOM和diff算法来答,还可以再加上shouldComponentUpdate来说一下,嗯....应该还有单向数据流,比如说父组件改变子组件是否会跟着改变之类的

@vkboo
Copy link

vkboo commented Jun 2, 2021

针对“单向数据流”的含义,我看有的文章指的是数据流向只能父组件到子组件,有的文章又像上面说的数据驱动视图。后者才是原本的含义吧?

@zoulipeng
Copy link

React的渲染原理涉及到Virtual Dom(虚拟DOM),当state或props改变时.利用Diff算法与之前的树进行对比,计算出Virtual DOM中真正变化的部分进行更新并渲染到页面上,实现按需更新减少对真实DOM操作,实现性能优化.

@erencoding
Copy link

image
主要有两个阶段、三个部分,包括Render阶段的

  1. scheduler: 调度器,负责为不同任务分配优先级,优先级高的任务先reconcile
  2. reconciler:协调器,找出变化的节点打上不同标签,表示不同的副作用,比如插入、替换、删除
  3. renderer:渲染器,将reconciler中打好标签的节点渲染到视图,或者执行标签的副作用更新界面

三者是怎么配合的了?

  1. JSX经过babel编译为createElement,createElement执行之后形成virtualDom(虚拟节点)
  2. 无论是mount还是update,渲染任务都会先经sheduler的调度,高优先级的任务优先进入reconcile环节。初始化任务的时候会计算一个过期时间,优先级高的过期时间短,优先级低的过期时间长。在最新的lane模型中,可以根据二进制1的位置决定优先级,通过二进制的计算判断优先级是否能够渲染。如果是非常耗时的任务,在一个时间片中没有执行完,会暂停当前Fiber的计算,让出执行权给浏览器。这个计算过程其实是计算Fiber的差异,并标记副作用
  3. 在mount和update时,会比较新旧Fiber节点的差异,这个过程就是diff,将带有副作用的节点标记出来。这些副作用有Placement(插入)、Update(更新)、Deletetion(删除)等,将副作用全部放入effectList(副作用列表)中,在commit阶段会执行这些副作用
  4. 在commit阶段,renderer将effectList中的副作用应用到真实节点,这个过程会应用到不同的渲染器,浏览器环境中react-dom,在canvas或svg就是react-art

另外也可以看mount和update在render和commit阶段如何工作的?

  1. 在mount时,在render阶段构建新的workInProgressFiber树,然后将Fiber节点标记副作用Placement(插入),将副作用放入effectList中。在commit阶段会执行effectList的副作用到真实节点。
  2. 在update时,在render阶段将jsx与current Fiber树进行比较,生成workInProgress树,通过diff在变化的Fiber标记副作用,加入到effectList中。在commit阶段会执行effectList的副作用到真实节点。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
react react
Projects
None yet
Development

No branches or pull requests