haizlin / fe-interview

前端面试每日 3+1,以面试题来驱动学习,提倡每日学习与思考,每天进步一点!每天早上5点纯手工发布面试题(死磕自己,愉悦大家),6000+道前端面试题全面覆盖,HTML/CSS/JavaScript/Vue/React/Nodejs/TypeScript/ECMAScritpt/Webpack/Jquery/小程序/软技能……
http://www.h-camel.com
MIT License
25.4k stars 3.25k forks source link

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

Open haizhilin2013 opened 5 years ago

haizhilin2013 commented 5 years ago

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

chenchujuan commented 5 years ago

自上而下的单向数据流

UserRegistering commented 4 years ago

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

liuyingbin19222 commented 4 years ago
hdugaojing commented 4 years ago

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

wjrhyw commented 4 years ago

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

LiFeng007 commented 4 years ago

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

pureZjr commented 3 years ago

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

ouuz commented 3 years ago

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

vkboo commented 3 years ago

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

zoulipeng commented 2 years ago

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

erencoding commented 2 years ago

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的副作用到真实节点。