UI 開發(fā)有兩個問題:
展示復(fù)用目前基本使用組件化來解決,,邏輯復(fù)用一直以來都沒有特別好的解決方案。React 從一開始的 mixin ,到 高階組件 以及 Render Props ,,都是在試圖解決這個問題,,但是都引入了一些別的問題。 Mixins
Higher-order Components
Render Props(Vue 中的 Renderless Components)
Hooks在前段時間 Hooks 發(fā)布后,我認(rèn)為 React 找到了【有狀態(tài)】組件【函數(shù)式】【復(fù)用邏輯】的解決方案,。 實現(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++; |
|