简易版hooks的实现(useState)
90行代码==按照hooks源码逻辑实现的简易版的useState,去除了优先级,实现了多个state
其他hooks的实现也跟这个差不多,只是执行的时间不同以及memoizeState保存的数据不同而已
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
let isMount = true;
let workInProgressHook = null;//全局变量,指向当前的正在执行的hooks
const fiber = {
memoizedState: null,
stateNode: App
};
function run() {
workInProgressHook = fiber.memoizedState;
const app = fiber.stateNode();
isMount = false;
return app;
}
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;
run();
}
function useState(initialState) {
let hook;
if (isMount) {
hook = {
queue: {
pending: null
},
memoizedState: initialState,
next: null
};
if (!fiber.memoizedState) {
fiber.memoizedState = hook;
} else {
workInProgressHook.next = hook;
}
workInProgressHook = hook;
} else {
hook = workInProgressHook;
workInProgressHook = workInProgressHook.next;
}
let baseState = hook.memoizedState;
if (hook.queue.pending) {
let firstUpdate = hook.queue.pending.next;
// hook.queue.pending保存着最后一个update,所以它的next是第一个update
do {
const action = firstUpdate.action;
baseState = action(baseState);
firstUpdate = firstUpdate.next;
} while (firstUpdate !== hook.queue.pending.next);
hook.queue.pending = null;
}
hook.memoizedState = baseState;
return [baseState, dispatchAction.bind(null, hook.queue)]
}
function App() {
const [num, updateNum] = useState(0);
const [states, triggerState] = useState(true);
console.log("isMount?", isMount);
console.log('num', num);
console.log('states', states);
return {
onclick() {
updateNum(num => num + 1);
},
trigger() {
triggerState(states => !states);
}
}
}
window.app = run();
</script>
</body>
</html>
多次调用onclick只改变了num的值,states的值不改变,多次调用trigger只改变了states的值,num的值不改变,所以两个状态是互相不干扰的,实现了useState的功能!