浏览前须知
流程图的内容90%来自于React技术揭秘一书,对其内容进行整顿,不便正在学习源码的同学们可能系统性把每个要害知识点给串联起来,上面JPG图片比拟含糊,图片宽高比较大,用手机关上pdf,观看起来也不不便,倡议用电脑跳转上面各个pdf地址进行查看,带着问题来浏览。
React理念
1、react15与react > 16架构区别性?\
2、Fiber节点的组成?\
3、Fiber树的构造?何为深度优先遍历?\
4、Fiber工作原理(双缓存技术)?\
5、Fiber Mount与Update流程是怎么样?\
6、JSX与Fiber的区别?pdf地址: bin-blog.oss-cn-shenzhen.aliyuncs.com/react/react…
React render阶段
1、进入render阶段前须要干什么(判断是否异步可中断更新)?\
2、Fiber节点的创立和Fiber树的构建如何开始(performUnitOfWork)?\
3、“递”阶段beginWork如何工作?\
4、‘归阶段’completeWork如何工作?\
5、如何判断是mount还是update?\
6、render阶段最终的产物是什么(effectList的生成、fiber节点的创立)?pdf地址: bin-blog.oss-cn-shenzhen.aliyuncs.com/react/react…
React commit阶段
1、commit阶段如何开启(commitRoot办法)?\
2、before mutation阶段之前做了什么(flushPassiveEffects(),触发useEffect回调与其余同步工作)?\
3、rootFiber的effectTag不在effectList怎么办?\
4、before mutation阶段(执行Dom操作之前)做了什么?\
5、mutation阶段(执行Dom操作)做了什么?\
6、layout阶段(执行Dom操作后)做了什么?\
7、layout之后做了什么?\
8、最终产物是什么?pdf地址: bin-blog.oss-cn-shenzhen.aliyuncs.com/react/react…
React Diff算法
1、什么是diff算法?\
2、diff概念?\
3、diff算法产生的阶段?\
4、diff的预设限度?\
5、diff如何实现?pdf地址: bin-blog.oss-cn-shenzhen.aliyuncs.com/react/react…
React 状态更新
1、触发状态更新要害链路?\
2、触发状态更新有哪些办法?\
3、HostRoot、ClassComponent的Update对象构造?\
4、ClassComponent、HostRoot的UpdateQueue构造?\
5、updateQueue的工作流程?\
6、调度优先级的过程?\
7、为什么componentWillXXX会触发屡次,要加个unsafe_?\
8、如何保障Update不失落?\
9、ReactDOM.render的流程?\
10、this.setState、this.forceUpdate的流程?\
11、React入口有哪三种模式?pdf地址: bin-blog.oss-cn-shenzhen.aliyuncs.com/react/react…
React Hook
1、一个极简的useState Hook的实现(强烈推荐,上面把这部分的代码贴出来了,对了解hook有帮忙)\
2、Hook 的数据结构(相似updateQueue)\
3、mount/update的调起办法会以不同dispatcher辨别\
4、useState与useReducer原理概览(比照下面极简useState hook的实现)\
5、usEffect(通过前几个流程图所讲flushPassiveEffects办法进行切入了解)概览\
6、useRef原理概览?ref的工作流程,render阶段做了什么?commit阶段做了什么?\
7、useMemo、useCallback原理概览,以及mount、update时两者的区别pdf地址\
bin-blog.oss-cn-shenzhen.aliyuncs.com/react/react…
极简useState Hook的实现
// 首次render时是mount
let isMount = true;
// 通过workInProgressHook变量指向以后正在工作的hook
let workInProgressHook;
// App组件对应的fiber对象
const fiber = {
// 保留该FunctionComponent对应的Hooks链表
memoizedState: null,
// 指向App函数
stateNode: App
};
// APP组件
function App() {
const [num, updateNum] = useState(0);
console.log(`${isMount ? 'mount' : 'update'} num: `, num);
return {
click() {
updateNum(num => num + 1);
}
}
}
// 模仿React开始调度更新
function schedule() {
// 更新前将workInProgressHook重置为fiber保留的第一个Hook
// 通过workInProgressHook变量指向以后正在工作的hook
workInProgressHook = fiber.memoizedState;
// 触发组件render
fiber.stateNode();
// 组件首次render为mount,当前再触发的更新为update
isMount = false;
}
// 更新时底层驱动函数
function dispatchAction(queue, action) {
// 创立update
const update = {
action, // 更新执行的函数
next: null // 与同一个Hook的其余更新造成链表
}
// 环状单向链表操作
// 产生的update保留在useState对应的hook.queue
if (queue.pending === null) {
update.next = update;
} else {
update.next = queue.pending.next;
queue.pending.next = update;
}
queue.pending = update;
// 模仿React开始调度更新
schedule();
}
function useState(initialState) {
let hook;
if (isMount) {
// mount时须要生成hook对象
// 保留update的queue,即上文介绍的queue
hook = {
queue: {
pending: null
},
// 保留hook对应的state
memoizedState: initialState,
// 与下一个Hook连贯造成单向无环链表
next: null
}
// 将hook插入fiber.memoizedState链表开端
if (!fiber.memoizedState) {
fiber.memoizedState = hook;
} else {
workInProgressHook.next = hook;
}
// 挪动workInProgressHook指针
workInProgressHook = hook;
} else {
// update时从workInProgressHook中取出该useState对应的hook
hook = workInProgressHook;
// 在组件render时,每当遇到下一个useState,咱们挪动workInProgressHook的指针。
// 这样,只有每次组件render时useState的调用程序及数量保持一致,那么始终能够通过workInProgressHook找到以后useState对应的hook对象。
workInProgressHook = workInProgressHook.next;
}
let baseState = hook.memoizedState;
if (hook.queue.pending) {
// 获取update环状单向链表中第一个update
let firstUpdate = hook.queue.pending.next;
do {
// 执行update action
const action = firstUpdate.action;
baseState = action(baseState);
firstUpdate = firstUpdate.next;
// 最初一个update执行完后跳出循环
} while (firstUpdate !== hook.queue.pending.next)
// 清空queue.pending
hook.queue.pending = null;
}
// 将update action执行完后的state作为memoizedState
hook.memoizedState = baseState;
return [baseState, dispatchAction.bind(null, hook.queue)];
}
发表回复