前言
最近在筹备面试。温习了一些react的知识点,特此总结。
开始
React 生命周期
react 16以前的生命周期是这样的
组件在首次渲染时会被实例化,而后调用实例下面的componentWillMount,render和componentDidMount函数。组件在更新渲染时能够调用componentWillReceiveProps,shouldComponentUpdate,componentWillUpdate,render和componentDidUpdate函数。组件在卸载时能够调用componentWillUnmount函数。
借图:
从 React v16.3 开始,React 倡议应用getDerivedStateFromProps
和getSnapshotBeforeUpdate
两个生命周期函数代替 componentWillMount
,componentWillReceiveProps
和componentWillUpdate
三个生命周期函数。这里须要留神的是 新增的两个生命周期 函数和原有的三个生命周期函数必须离开应用,不能混合应用
目前的生命周期(借图):
componentWillMount存在的问题
有人认为在componentWillMount中能够提前进行异步申请,防止白屏。然而react在调用render渲染页面的时候,render并不会期待异步申请完结,再获取数据渲染
。这么写是有潜在隐患的。
而在react fiber之后 可能在一次渲染中屡次调用。起因是:react fiber技术应用增量渲染来解决掉帧的问题,通过requestIdleCallback调度执行每个工作单元,能够中断和复原,生命周期一旦中断,复原之后会从新跑一次之前的生命周期
新的生命周期
static getDerivedStateFromProps
- 触发工夫(v16.4修改):组件每次被rerender的时候,包含在组件构建之后(render之前最初执行),每次获取新的props或state之后。在v16.3版本时,组件state的更新不会触发该生命周期
- 每次接管新的props之后都会返回一个对象作为新的state,返回null则阐明不须要更新state
- 配合componentDidUpdate,能够笼罩componentWillReceiveProps的所有用法
getSnapshotBeforeUpdate
- 触发工夫: update产生的时候,在render之后,在组件dom渲染之前。
- 返回一个值,作为componentDidUpdate的第三个参数。
- 配合componentDidUpdate, 能够笼罩componentWillUpdate的所有用法。
React Fiber
因为React渲染/更新过程一旦开始无奈中断,继续占用主线程,主线程忙于执行JS,得空他顾(布局、动画),造成掉帧、提早响应(甚至无响应)等不佳体验。fiber应运而生。
Fiber 是对react reconciler(和谐) 外围算法的重构。要害个性如下:
- 增量渲染(把渲染工作拆分成块,匀到多帧)
- 更新时可能暂停,终止,复用渲染工作
- 给不同类型的更新赋予优先级
- 并发方面新的根底能力
增量渲染用来解决掉帧的问题,渲染工作拆分之后,每次只做一小段,做完一段就把工夫控制权交还给主线程,而不像之前长时间占用。
Fiber tree
- Fiber之前的reconciler(被称为Stack reconciler)自顶向下的递归mount/update,无奈中断(继续占用主线程),这样主线程上的布局、动画等周期性工作以及交互响应就无奈立刻失去解决,影响体验。
- Fiber解决这个问题的思路是把渲染/更新过程(递归diff)拆分成一系列小工作,每次查看树上的一小部分,做完看是否还有工夫持续下一个工作,有的话持续,没有的话把本人挂起,主线程不忙的时候再持续。
fiber树其实是一个单链表构造
,child指向第一个子节点,return指向父节点,sibling指向下个兄弟节点。构造如下:
// fiber tree节点构造{ stateNode, child, return, sibling, ...}
Fiber reconciler
reconcile过程分为2个阶段:
1.(可中断)render/reconciliation 通过结构workInProgress tree得出change
2.(不可中断)commit 利用这些DOM change(更新DOM树、调用组件生命周期函数以及更新ref等外部状态)
构建workInProgress tree的过程就是diff的过程,通过requestIdleCallback来调度执行一组工作,每实现一个工作后回来看看有没有插队的(更紧急的),每实现一组工作,把工夫控制权交还给主线程,直到下一次requestIdleCallback回调再持续构建workInProgress tree
生命周期也被分成了两个阶段:
// 第1阶段 render/reconciliationcomponentWillMountcomponentWillReceivePropsshouldComponentUpdatecomponentWillUpdate// 第2阶段 commitcomponentDidMountcomponentDidUpdatecomponentWillUnmount
第1阶段的生命周期函数可能会被屡次调用,默认以low优先级执行,被高优先级工作打断的话,稍后从新执行。
fiber tree与workInProgress tree
双缓冲技术:指的是workInProgress tree结构结束,失去的就是新的fiber tree,而后把current指针指向workInProgress tree,因为fiber与workInProgress相互持有援用,旧fiber就作为新fiber更新的预留空间,达到复用fiber实例的目标。
每个fiber上都有个alternate属性,也指向一个fiber,创立workInProgress节点时优先取alternate,没有的话就创立一个
let workInProgress = current.alternate;if (workInProgress === null) { //... workInProgress.alternate = current; current.alternate = workInProgress;} else { // We already have an alternate. // Reset the effect tag. workInProgress.effectTag = NoEffect; // The effect list is no longer valid. workInProgress.nextEffect = null; workInProgress.firstEffect = null; workInProgress.lastEffect = null;}
这么做的益处:
- 可能复用外部对象(fiber)
- 节俭内存调配、GC的工夫开销
fiber 中断 复原
中断:查看以后正在解决的工作单元,保留以后成绩(firstEffect, lastEffect),批改tag标记一下,迅速收尾并再开一个requestIdleCallback,下次有机会再做
断点复原:下次再解决到该工作单元时,看tag是被打断的工作,接着做未实现的局部或者重做
P.S.无论是工夫用尽“天然”中断,还是被高优工作粗犷打断,对中断机制来说都一样。
React setState
在代码中调用setState函数之后,React 会将传入的参数对象与组件以后的状态合并,而后触发所谓的和谐过程(Reconciliation)。通过和谐过程,React 会以绝对高效的形式依据新的状态构建 React 元素树并且着手从新渲染整个UI界面。在 React 失去元素树之后,React 会主动计算出新的树与老树的节点差别,而后依据差别对界面进行最小化重渲染。在差别计算算法中,React 可能绝对准确地晓得哪些地位产生了扭转以及应该如何扭转,这就保障了按需更新,而不是全副从新渲染。
setState调用时有时是同步的(settimeout,自定义dom事件),有时是异步的(一般调用)
React 事件机制
React事件是通过事件代理,在最外层的 document上对事件进行对立散发,并没有绑定在实在的 Dom节点上。
而且react外部对原生的Event对象进行了包裹解决。具备与浏览器原生事件雷同的接口,包含 stopPropagation()
和 preventDefault()
。