函数式编程
- 纯函数
 reducer必须是一个纯函数,即没有副作用的函数,不修改输入值,相同的输入一定会有相同的输出
- 不可变值
 state必须是不可变值,否则在shouldComponentUpdate中无法拿到更新前的值,无法做性能优化操作。
vdom 和 diff 算法
JSX 本质
- 是 React.createElement函数- React.createElement(tag, props, child1, child2, child3)
- React.createElement(tag, props, [child1, child2, child3])
 
- 执行生成 vnode
const elem = <div><p>aaa</p><p style={{ color: 'red' }}>bbb</p></div>;
const elem = React.createElement("div", null, React.createElement("p", null, "aaa"), React.createElement("p", { style: { color: "red" } }, "bbb")
);
const lisElem = <div>{this.state.list.map((item, index) => {return (<span key={item.id}>{item.name}</span>);})}
</div>;
const listElem = React.createElement("div", null, (void 0).state.list.map((item, index) => {return React.createElement("span", { key: item.id }, item.name);})
);
合成事件
- react的事件不是原生事件- MouseEvent,而是合成事件- SyntheticEvent
- react16是挂载到- document上的;- react17开始是挂载到- root上的
- 事件处理函数交给合成事件,事件冒泡到 document/root上进行处理
出处:https://coding.imooc.com/lesson/419.html#mid=41943
合成事件的好处:
- 更好的兼容性和跨平台:比如 react-native
- 全部挂载到 document/root上,减少内存消耗,避免频繁解绑
- 方便事件的统一管理(事务机制)
出处:https://coding.imooc.com/lesson/419.html#mid=41943
React17 开始挂载到 root 组件上:
 - document 只有一个,root 有多个,有利于多个 react 版本共存,例如:微前端
setState 和 batchUpdate
setState 主流程
出处:https://coding.imooc.com/lesson/419.html#mid=41943
- 异步:左边分支
- 非异步:右边分支
isBatchingUpdates
class ListDemo extends React.Componentconstructor(props) {// ...}render() {// ...}increase = () => {// 开始: 处于 batchUpdate// isBatchingiUpdates = true this.setState({count: this.state.count + 1});// 结束// isBatchingUpdates = false}
}
class ListDemo extends React.Componentconstructor(props) {// ...}render() {// ...}increase = () => {// 开始: 处于 batchUpdate// isBatchingUpdates = true setTimeout(() => {// 此时 isBatchingUpdates 是 falsethis.setState({count: this.state.count + 1});});// 结束// isBatchingUpdates = false}
}
componentDidMount() {// 开始: 处于 batchUpdate// isBatchingUpdates = true document.body.addEventListener('click', () => {// 此时 isBatchingUpdates 是 falsethis.setState({count: this.state.count + 1});console.log('count in body event', this.stae.count);});// 结束// isBatchingUpdates = false
}
哪些能命中 batchUpdate 机制:
- 生命周期(和它调用的函数)
- React中注册的事件(和它调用的函数)
- React可以“管理”的入口
transaction 事务机制
class ListDemo extends React.Componentconstructor(props) {// ...}render() {// ...}increase = () => {// 	开始:处于 batchUpdate// isBatchingUpdates = true// 其他任何操作// 结束// isBatchingUpdates = false}
}
出处:https://coding.imooc.com/lesson/419.html#mid=41943
transaction.initialize = function() {console.log('initialize');
};transaction.close = function() {console.log('close');
};function method() {console.log('abc');
}transaction.perform(method);// 输出 'initialize'
// 输出 'abc'
// 输出 'close'
react 组件渲染过程
- JSX如何渲染为页面:- 初始化时候继承 props和 生成state
- 通过 render()函数 生成vnode
- patch(elem, vnode):通过- patch函数将- vonde更新到- dom上
 
- 初始化时候继承 
- setState之后如何更新页面:- setSate(newState)->- dirtyComponents(可能有子组件):通过- setState产生新的- state,存到- dirtyComponent进行异步更新
- 通过 render()函数生成新的vnode
- patch(elem, vnode):再通过- patch函数用 newVnode 去更新旧的 vnode
 
react-fiber
react 的 patch 被拆分为两个阶段:
- reconciliation阶段:执行- diff算法,纯- js计算
- commit阶段:将- diff结果渲染成- dom
背景
- js是单线程的,且和- dom渲染共用一个线程
- 当组件足够复杂,组件更新时计算和渲染压力都很大
- 同时再有 dom操作需求,比如动画、鼠标拖拽等,那么将会卡顿
解决方案:fiber
fiber
- react内部的运行机制,开发者体会不到
- 将 reconciliation阶段进行任务拆分(commit无法拆分)
- dom需要渲染时暂停,空闲时恢复
- 通过 window.requestidleCallback进行控制(并非所有浏览器支持)
FQA
- JSX的本质是什么?- jsx的本质是- React.createElement函数,执行生返回- vnode。
 
- react组件更新渲染的过程。- 初始化时候继承 props和 生成state
- 通过 render()函数生成vnode
- 再通过 patch函数将vonde渲染成真实dom
- 通过 setState修改产生新的state
- 触发 re-render生成新的vnode
- 再通过 patch函数用newVnode去更新旧的vnode
 
- 初始化时候继承 
- react为什么要将- patch过程拆分成- reconciliation和- commit两个阶段?- 因为js是单线程的,且和dom渲染共用一个线程
- 当组件很复杂的时候,组件更新时计算和渲染压力都很大
- 同时再有 dom操作需求,比如动画、鼠标拖拽等,那么将会卡顿
 
- 因为



