函数式编程
一种编程范式
- 纯函数
- 不可变值
vdom 和 diff 算法
- h 函数
- vnode 数据结构
- patch 函数
diff 算法(和 vue 的核心概念和实现思路一致)
- 只比较同一层级,不跨级比较
- tag 不相同,则直接删掉重建,不再深度比较
- tag 和 key,两者都相同,则认为是相同节点,不再深度比较
vue2 和 vue3 和 react 实现 vdom 的细节不一样 核心概念和实现思路一致
JSX 本质(编译出来的是什么)
等同于 vue 的模板
vue 的模板不是 html
jsx 不是 js
const ele = <div className="d" id="id1">
<p>some p</p>
<p style={{fontSize: "20px", width: "200px", height: "200px"}}>设置 style</p>
<p>some p</p>
<input onClick={(event)=> console.log(event)} />
<img src={imgSrc} />
{/* 组件 */}
<CustomComponent submit={onSubmit} />
<ul>
{this.state.list.map((item,index) => <li key={item.id}>index: {index} - title: {item.title}</li>)}
</ul>
</div>
// jsx ===> 转化为 vnode
const ele = /*#__PURE__*/React.createElement("div", {
className: "d",
id: "id1"
}, /*#__PURE__*/React.createElement("p", null, "some p"), /*#__PURE__*/React.createElement("p", {
style: {
fontSize: "20px",
width: "200px",
height: "200px"
}
}, "\u8BBE\u7F6E style"), /*#__PURE__*/React.createElement("p", null, "some p"), /*#__PURE__*/React.createElement("input", {
onClick: event => console.log(event)
}), /*#__PURE__*/React.createElement("img", {
src: imgSrc
}), /*#__PURE__*/React.createElement(CustomComponent, {
submit: onSubmit
}), /*#__PURE__*/React.createElement("ul", null, (void 0).state.list.map((item, index) => /*#__PURE__*/React.createElement("li", {
key: item.id
}, "index: ", index, " - title: ", item.title))));
jsx 中组件名首字母必须大写
合成事件
所有事件挂载到 document (仅仅在 React16 中)上,react17 绑定到 root 组件上,有利于多个 React 版本并存,例如微前端
event 不是原生的,是 SyntheticEvent 合成事件对象
更好的兼容性和跨平台 减少内存消耗,避免频繁解绑 方便事件的统一管理(事务机制)
setState 和 batchUpdate
setState:
- 有时异步(普通使用),有时同步(setTimeout,自定义的 DOM 事件)
- 有时合并(对象形式),有时不合并(函数形式)
setState 是异步还是同步?
- setState 本身没有异步同步
- 看是否命中 batchUpdate 机制
- 判断 isBatchingUpdates
哪些能命中 batchUpdate 机制?
- 生命周期(和它里面所调用的函数)
- React 中注册的事件(和它里面所调用的函数)
- React 可以 “ 管理 “ 的入口
哪些不能命中 batchUpdate 机制?
- setTimeout,setInterval(和它里面所调用的函数)
- 自定义 DOM 事件(和它里面所调用的函数)
- React “ 管不到 “ 的入口
transaction 事务机制
let transaction = {
initialize: () => console.log("initialize"),
close: () => console.log("close"),
perform: (method) => method()
}
let method = () => console.log("method")
transaction.initialize()
transaction.perform(method)
transaction.close()
组件渲染和更新过程
- JSX 本质就是一个 createElement 函数
- 执行生成 vnode
- patch(elem, vnode) 和 patch(vnode, newVnode)
点击查看【processon】
组件渲染过程:
- props state
- render() 函数 生成 vnode
- patch(elem, vnode)
组件更新过程:
- setState(newState) —> dirtyComponents ( 可能有子组件 )
- render() 生成 newVnode
- patch(vnode, newVnode)
patch 在 react 中分为 2 个阶段:
- reconciliation 阶段 - 执行 diff 算法,纯 JS 计算
- commit 阶段 - 将 diff 算法结果渲染到 DOM
考虑到性能问题
React fiber
在 reconciliation 阶段进行拆分为多任务(commit 阶段 无法拆分)
DOM 需要渲染时暂停,空闲时恢复
window.requestIdleCallback
注意:safari 浏览器不支持