每次调用顺序索引必须一样
返回初始状态变量,和更改状态方法
调用更改状态方法,更新状态并重新渲染
let lastStates = []
let index;
function useState(initValue) {
let state = lastStates[index] || initValue;
let currIndex = index;
let setState = (newState) => {
lastStates[currIndex] = newState;
render();
}
index++
return [state,setState]
}
2:实现简版的 useMemo
如果有dependencies未变化,返回上次对象的值
如果dependencies有变化,执行callback,返回新对象
let lastMemo
let lastMemoDependencies
function useMemo(callback,dependencies) {
if (!lastMemo) {
lastMemo = callback();
lastMemoDependencies = dependencies;
}
else {
let changed = !dependencies.every((item, idx) => item === lastMemoDependencies[idx])
if (changed) {
lastMemo = callback();
lastMemoDependencies = dependencies;
}
}
return lastMemo;
}
3:实现简版的 useCallback
如果有dependencies未变化,返回上次callback
如果dependencies有变化,返回新的callback
let lastCallback
let lastCallbackDependencies
function useCallback(callback,dependencies) {
if (!lastCallback) {
lastCallback = callback;
lastCallbackDependencies = dependencies;
}
else {
let changed = !dependencies.every((item, idx) => item === lastCallbackDependencies[idx])
if (changed) {
lastCallback = callback;
lastCallbackDependencies = dependencies;
}
}
return lastCallback;
}
4:实现简版的 useReducer
传入reducer,
返回状态和dispatch函数
let lastState
function useReducer(reducer, initValue) {
lastState=lastState || initValue;
let dispatch = function (action) {
lastState= reducer(lastState, action);
render();
}
return [lastState,dispatch]
}
5:实现简版的 useContext
共享变量
let Context = React.createContext();
function useContext(Context) {
console.log('Context',Context);
return Context._currentValue
}
此处Provider组件可以共享变量,useContext可以拿到对应的变量数据,在Counter组件中就可以使用useContext获取变量
<Context.Provider value={{ state, setState }}>
<Counter></Counter>
</Context.Provider>
6:实现简版的 useEffect
浏览器事件环:
1)执行脚本代码(宏任务队列中取出)
2)进入主执行栈,依次执行
3)如遇到setTimeout,ajax,event, 把对应的回调放入宏任务队列, 宏任务队列在页面渲染之后执行
4)如遇到Promise, 把对应的回调放入微任务队列, 在页面渲染之前执行,所以任务会阻碍页面的渲染
5)显示器刷新率是60HZ, 每秒钟刷新60次, 也是就是16.67毫秒刷新一次
//在浏览器渲染后执行,不会阻塞浏览器运行
let lastDependencies
function useEffect(callback,dependencies) {
if (!lastDependencies) {
lastDependencies = dependencies;
setTimeout(() => {
callback();
}, 0);
}
else {
let changed = !dependencies.every((item, idx) => item === lastDependencies[idx])
if (changed) {
lastDependencies = dependencies;
callback();
}
}
}
let lastLayOutDependencies
function useLayoutEffect(callback,dependencies) {
if (!lastLayOutDependencies) {
lastLayOutDependencies = dependencies;
queueMicrotask(callback);
// Promise.resolve().then(callback)
}
else {
let changed = !dependencies.every((item, idx) => item === lastLayOutDependencies[idx])
if (changed) {
lastLayOutDependencies = dependencies;
queueMicrotask(callback);
// Promise.resolve().then(callback)
}
}
}
7:实现简版的 useReducer
function useReducer(reducer, initialState) {
const [state, setState] = useState(initialState);
function dispatch(action) {
const nextState = reducer(state, action);
setState(nextState);
}
return [state, dispatch];
}
<!DOCTYPE html>
<html lang="en">
<script>
// display Hello World and then page stuck because the infinite loop
setTimeout(() => {
while (true) {}
console.log('setTimeout');
document.body.style.backgroundColor = '#ccc';
}, 0);
// no Hello World display and page stuck because the infinite loop
Promise.resolve().then(() => {
while (true) {}
console.log('Promise');
});
</script>
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
Hello World
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link
rel="stylesheet"
href="/home/hkjc/Documents/JeffH/rt-rbk/node_modules/swiper/dist/css/swiper.min.css"
/>
<script src="/home/hkjc/Documents/JeffH/rt-rbk/node_modules/swiper/dist/js/swiper.min.js"></script>
<style>
.mySwiper {
width: 300px;
height: 500px;
background-color: gray;
overflow: hidden;
}
</style>
</head>
<body>
<div class="mySwiper">
<div class="swiper-wrapper">
<div class="swiper-slide">Slide 1</div>
<div class="swiper-slide">Slide 2</div>
<div class="swiper-slide">Slide 3</div>
<div class="swiper-slide">Slide 4</div>
<div class="swiper-slide">Slide 5</div>
<div class="swiper-slide">Slide 6</div>
<div class="swiper-slide">Slide 7</div>
<div class="swiper-slide">Slide 8</div>
<div class="swiper-slide">Slide 9</div>
<div class="swiper-slide">Slide 10</div>
<div class="swiper-slide">Slide 11</div>
<div class="swiper-slide">Slide 12</div>
<div class="swiper-slide">Slide 13</div>
<div class="swiper-slide">Slide 14</div>
<div class="swiper-slide">Slide 15</div>
<div class="swiper-slide">Slide 16</div>
<div class="swiper-slide">Slide 17</div>
<div class="swiper-slide">Slide 18</div>
<div class="swiper-slide">Slide 19</div>
<div class="swiper-slide">Slide 20</div>
</div>
</div>
</body>
</html>
<script>
var swiper = new Swiper('.mySwiper', {
direction: 'vertical',
slidesPerView: 'auto',
initialSlide: 0,
freeMode: true,
observer: true,
observeParents: true,
});
const touchStart=()=>{
debugger
console.log(`touchstart `)
}
const touchMove=()=>{
console.log(`touchMove `)
}
const touchEnd=()=>{
console.log(`touchEnd `)
}
window.addEventListener('touchstart',touchStart)
window.addEventListener('touchmove',touchMove)
window.addEventListener('touchend',touchEnd)
</script>