1:实现简版的 useState

每次调用顺序索引必须一样
返回初始状态变量,和更改状态方法
调用更改状态方法,更新状态并重新渲染
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>

 

 

 
 
posted on 2022-07-26 09:51  码农-编程小子  阅读(96)  评论(0编辑  收藏  举报