久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

實現(xiàn) React Hooks

 行者花雕 2021-10-06

UI 開發(fā)有兩個問題:

  1. 展示復(fù)用

  2. 邏輯復(fù)用

展示復(fù)用目前基本使用組件化來解決,,邏輯復(fù)用一直以來都沒有特別好的解決方案。React 從一開始的 mixin ,到 高階組件 以及 Render Props ,,都是在試圖解決這個問題,,但是都引入了一些別的問題。

Mixins

  1. 命名空間沖突

  2. 數(shù)據(jù)來源不清晰

Higher-order Components

  1. props 屬性來源不清晰

  2. props 上命名沖突

  3. 額外的組件渲染帶來性能問題

Render Props(Vue 中的 Renderless Components)

  1. 解決了 命名空間沖突,、數(shù)據(jù)來源不清晰的問題,,仍然會帶來額外組件實例的性能消耗

Hooks

在前段時間 Hooks 發(fā)布后,我認(rèn)為 React 找到了【有狀態(tài)】組件【函數(shù)式】【復(fù)用邏輯】的解決方案,。
先說有狀態(tài):一般來說,,無狀態(tài)組件直接使用函數(shù)組件就行,省去了實例化的樣板代碼和性能消耗,。不涉及到 state 的存取,,可以直接寫個 helper 函數(shù)處理一下,方便又快捷,。
再說函數(shù)式:class 組件是面向?qū)ο蟮?,每一次聲明、聲明周期都逃不開 this,,而 hooks 更加函數(shù)式,,調(diào)用一個函數(shù),傳入的是初始值,,返回修改值,,沒有副作用。
最后說復(fù)用邏輯:DRY,,一般來說,,相同的代碼不寫第二次,在 class 組件中,,通過生命周期方法對 state 修改,,然后 rerender,在使用了 hooks 以后,,我們可以通過 hooks 觸發(fā) render,,render 調(diào)用 hooks 時,根據(jù)傳入值的比較,,來決定是否觸發(fā) render,,然后把 hooks 返回的值填充到頁面上。

實現(xiàn)

hooks 給人最直接的印象就是可以在 function 組件中使用 state 了,。但它也有著不同于 class 組件的心智模型,,從生命周期的思維跳到 update circle,剛開始 useEffect 總會寫一些無限循環(huán),。接下來我們先來寫一個簡易版的 useState,,來模仿 React,。

let state;
function useState(init) {
  function setState(newState) {
    if (typeof newState === "function") {
      // 支持舊值傳入更新
      state = newState(state);
    } else {
      state = newState;
    }
    // setState 后調(diào)用組件 render
    // render();
  }
  if (!state) {
    state = init;
  }
  return [state, setState];
}

上面就是一個 useState 了,接下來繼續(xù)寫 useEffect.

let _deps;
function useEffect(callback, deps) {
  if (
    deps === undefined || // 就是不傳 deps,,就是每次都執(zhí)行副作用
    (deps !== undefined && _deps === undefined) || // 就是初始化,,要執(zhí)行一次副作用
    !deps.every((dep, i) => dep === _deps[i]) // 如果不是每一項都相等,就執(zhí)行
  ) {
    callback();
  }
}

這就是 useEffect 基本實現(xiàn)了,,當(dāng)然還有一個問題,,callback 的 return 函數(shù)問題。

let _deps;
function useEffect(callback, deps) {
  if (
    deps === undefined || // 就是不傳 deps,,就是每次都執(zhí)行副作用
    (deps !== undefined && _deps === undefined) || // 就是初始化,,要執(zhí)行一次副作用
    !deps.every((dep, i) => dep === _deps[i]) // 如果不是每一項都相等,就執(zhí)行
  ) {
    // 如果有 cleanUp 就執(zhí)行清理
    if (typeof _deps._cleanUp === "function") {
      _deps._cleanUp();
    }
    _deps._cleanUp = callback();
  }
}

接下來,,還有個重要問題,,hooks 的順序問題,其實就是把 state 和 deps 存到數(shù)組里,。

let _arr = [];
let cursor = 0;
function useState(init) {
  const current = cursor;
  function setState(newState) {
    if (typeof newState === "function") {
      // 支持舊值傳入更新
      _arr[current] = newState(_arr[current]);
    } else {
      _arr[current] = newState;
    }
    // setState 后調(diào)用組件 render
    render();
  }
  if (!_arr[current]) {
    _arr[current] = init;
  }
  cursor++;
  return [_arr[current], setState];
}
function useEffect(callback, deps) {
  const effect = _arr[cursor] || {};
  const { _deps, _cleanUp } = effect;
  if (
    deps === undefined || // 就是不傳 deps,,就是每次都執(zhí)行副作用
    (deps !== undefined && _deps === undefined) || // 就是初始化,要執(zhí)行一次副作用
    !deps.every((dep, i) => dep === _deps[i]) // 如果不是每一項都相等,,就執(zhí)行
  ) {
    // 如果有 cleanUp 就執(zhí)行清理
    if (typeof _cleanUp === "function") {
      _cleanUp();
    }
    effect._cleanUp = callback();
    effect._deps = deps;
    _arr[cursor] = effect;
  }
  cursor++;

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多