美文网首页
useEffect 原理

useEffect 原理

作者: bestCindy | 来源:发表于2022-06-06 15:00 被阅读0次

    首先 useEffect 接收两个参数,回调函数(callback)和依赖的数组(desAry)

    function myUseEffect(callback, depsAry) {
    }
    

    需要判断下 callback 是否是函数,如果不是函数就报错

    function myUseEffect(callback, depsAry) {
      if (Object.prototype.toString.call(callback) !== '[object Function]') {
        throw new Error('myUseEffect 函数的第一个参数必须是函数')
      }
    }
    

    接着需要判断 depsAry 是否传递,如果没有传递直接调用回调函数就可以了

    if (typeof depsAry === 'undeifined') {
        callback();
    }
    

    还需要判断 depsAry 是否是一个数组,如果不是就报错

    if (typeof depsAry === 'undeifined') {
        callback();
    } else {
        if (Object.prototype.toString.call(depsAry) !== '[object Array]') {
            throw new Error('myUseEffect 函数的第二个参数必须是数组')
        }
    }
    

    如果是数组,需要拿当前的依赖值和上一次的依赖值作对比,如果有变化就执行 callback

    let preDepsAry = [];
    if (typeof depsAry === 'undeifined') {
        callback();
    } else {
        if (Object.prototype.toString.call(depsAry) !== '[object Array]') {
            throw new Error('myUseEffect 函数的第二个参数必须是数组')
        } else {
            const hasChanged = depsAry.every((dep, index) => dep === preDepsAry[index]) === false;
            if (hasChanged) {
                callback();
            }
            preDepsAry = depsAry;
        }
    }
    

    但是 useEffect 是可以有多个的,所以 preDepsAry 需要是一个二维数组

    这时候就需要索引来标识

    let effectIndex = 0;
    

    对比的时候

      if (Object.prototype.toString.call(depsAry) !== '[object Array]') {
            throw new Error('myUseEffect 函数的第二个参数必须是数组')
        } else {
            const prevDeps = preDepsAry[effectInjdex];
            const hasChanged = depsAry. ? depsAry.every((dep, index) => dep === prevDeps[index]) : false;
            if (hasChanged) {
                callback();
            }
            preDepsAry[effectIndex] = depsAry;
            effectIndex++:
        }
    

    再重新渲染的时候,effectIndex 需要恢复成 0

    function render() {
        stateIndex = 0;
        effectIndex = 0;
        ReactDom.render(<App />, document.getElementById('root'));
    }
    

    完整的代码:

    // 渲染函数
    function render() {
      stateIndex = 0;
      effectIndex = 0;
      ReactDOM.render(<App />, document.getElementById('root'));
    }
    
    const preDepsAry = [];
    let effectIndex = 0;
    
    function useMyEffect(callback, depsAry) {
      // 判断 callback 是否为函数
      if (Object.prototype.toString.call(depsAry) !== '[object Function]') {
        throw new Error('myUseEffect 的第二个参数必须是函数')
      }
      // 判断 depsAry 有没有传递
      if (typeof depsAry === 'undefined') {
        callback();
      } else {
        // 判断 depsAry 是否是数组
        if (Object.prototype.toString.call(depsAry) !== '[object Array]') {
          throw new Error('myUseEffect 的第二个参数必须是数组')
        } else {
          // 获取上一次依赖
          const prevDeps = preDepsAry[effectIndex];
          const hasChanged = prevDeps && depsAry.every((dep, index) => dep === prevDeps[index]);
          if (hasChanged) {
            callback();
          }
          preDepsAry[effectIndex] = depsAry;
          effectIndex++;
        }
      }
    }
    

    参考原文:https://juejin.cn/post/6970495764170539039

    相关文章

      网友评论

          本文标题:useEffect 原理

          本文链接:https://www.haomeiwen.com/subject/mrljmrtx.html