已实现性能
待优化解决问题
- 在某个时间段,将要更新的状态对立解决完,再更新DOM,目前是更新一次从新渲染一次
- 临时不能引入到React环境中,短少React的渲染办法待实现。但能够window中调试,能看到状态的更新
/** * 第一步: * isMount: 判断是第一次加载还是更新组件 * workInProgressHooks: 定义一个指针, 指向以后执行的useSate的 */ let isMount = true; let workInProgressHooks = null; /** * 第二步 * 定义 fiber节点 */ const fibier = { stateNode: App, memoizedState: null, // 以后fiber节点须要保护的hook }; /** * 第四步: 实现useState * @returns */ function useState(initialState) { let hook; if(typeof initialState === "function" ) { initialState = initialState(); } if (isMount) { hook = { memoizedState: initialState, // 以后这个hook须要保护的数据 next: null, // 为保障所有的useState能按序执行,所以须要实现 【链表构造】 queue: { pending: null, }, }; if (!fibier.memoizedState) { fibier.memoizedState = hook; } else { workInProgressHooks.next = hook; } workInProgressHooks = hook; } else { hook = workInProgressHooks; workInProgressHooks = workInProgressHooks.next; } // todo let beaseSate = hook.memoizedState; if(hook.queue.pending) { let firstUpate = hook.queue.pending.next; do{ const action = firstUpate.action; beaseSate = action(beaseSate); firstUpate = firstUpate.next; }while(firstUpate !== hook.queue.pending.next); hook.queue.pending = null; } hook.memoizedState = beaseSate; return [beaseSate, dispatchAction.bind(null, hook.queue)] } /** * 第五步:实现状态更新 * @returns */ function dispatchAction(queue, action) { const update = { action, next: null, }; // 第一次触发更新 if (queue.pending === null) { update.next = update; } else { update.next = queue.pending.next; queue.pending.next = update; } queue.pending = update; schedule(); } /** * 第三步 * 实现React 调度办法 * 调度办法运行后,即从新加载组建后,React会从新渲染 */ function schedule() { workInProgressHooks = fibier.memoizedState; const app = fibier.stateNode(); isMount = false; return app; } function App() { const [num1, setNum1] = useState(0); const [num2, setNum2] = useState(1); const [num3, setNum3] = useState(2); console.log("----最近一次更新--------", ); console.log("num1---", num1); console.log("num2-", num2); console.log("num3222", num3); return { onclick() { setNum1(num1 => num1 +1); setNum2(num2 => num2+1) setNum3(num3 => num3 +1) } } } window.app = schedule(); export default App;