模拟实现hook useState
2021-07-30 本文已影响0人
_嘿嘿_
//是否是第一次加载
let isMount = true;
//fiber 链表指针
let workInProgressHook = null;
//每个组件对应一个fiber对象
let fiber = {
//保存组件函数
stateNode:App,
//保存组件对应的hooks 数据链表
memoizedState:null
}
function useState(initialState){
//生成一个hook 对象
let hook;
if(isMount){
//第一次加载初始化hook对象
hook = {
memoizedState:initialState,
next:null,
queue:{
pending:null
}
}
//当是第一个useState的时候
if(!fiber.memoizedState){
fiber.memoizedState = hook;
}else{
//挂在到最后一个
workInProgressHook.next = hook;
}
//移动指针到最后一个
workInProgressHook = hook;
}else{
//更新,非第一次加载
//设置当前hook对象
hook = workInProgressHook;
//指针后移
workInProgressHook = hook.next;
}
//获取hook对应的值
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);
}
//重新给hook 赋值
hook.memoizedState = baseState;
return [baseState,dispatchAction.bind(null,hook.queue)]
}
//memoizedState更新方法
function dispatchAction(queue,action){
//创建要更新的链表(环状)
const update = {
action:action,
next:null
}
//与当前hook的操作对象queue关联
//当前hook没有更新
if(!queue.pending){
//u0 -> u0
update.next = update;
}else{
//u1 -> u0 ->u1
update.next = queue.pending.next;
queue.pending.next = update;
}
queue.pending = update;
//模拟调度
schedule();
}
//初始化调度render函数
function schedule(){
//指针指到第一个节点
workInProgressHook = fiber.memoizedState;
isMount = false;
//触发组件render
fiber.stateNode();
}
function App(){
const [num,updateNum] = useState(0);
const [num1,updateNum1] = useState(1);
console.log(num,num1);
return {
click:()=>{
updateNum(num=>num+1);
}
}
}
var test = App();
test.click();