<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【React】730- 從 loading 的 9 種寫法談 React 業(yè)務(wù)開發(fā)

          共 4619字,需瀏覽 10分鐘

           ·

          2020-09-30 00:45

          來源:ES2049
          Studiohttps://www.yuque.com/es2049/blog

          前言

          這是一篇比較全面講解 React 的文章,里面很多基礎(chǔ)知識希望你自己一邊查閱資料一邊學(xué)習(xí)。全文從業(yè)務(wù)開發(fā)中最常用見 loading 效果不同是實(shí)現(xiàn)講起,說下現(xiàn)在前端開發(fā)在業(yè)務(wù)上應(yīng)該有的思考。

          入門級操作

          State

          最簡單的實(shí)現(xiàn),我們在 Loading 組件內(nèi)部聲明一個(gè)狀態(tài),通過代碼邏輯判斷 loading 效果的展示。

          export?default?class?extends?Component?{
          ??...
          ??render()?{
          ????return?this.state.loading???<div?className="loader"?/>?:?<div>finishdiv>;
          ??}
          }

          完整演示

          https://codesandbox.io/s/j22nqo2k4y

          Props

          隨著業(yè)務(wù)的發(fā)展,這個(gè) Loading 組件用到的地方會(huì)非常多,上面這個(gè)代碼耦合了很多邏輯,為了讓這個(gè)組件能夠很好的復(fù)用,那我們抽離出組件的業(yè)務(wù)邏輯,將內(nèi)部狀態(tài)進(jìn)行提升,那這個(gè)組件就是一個(gè)能被復(fù)用的 UI 組件。

          export?default?function(props)?{
          ??return?props.loading???<div?className="loader"?/>?:?<div>finishdiv>;
          }

          完整演示

          https://codesandbox.io/s/k39472w027

          注:上面兩段代碼你可能會(huì)想,為什么 FuncClass 都能實(shí)現(xiàn)一個(gè)組件,他們有什么差別嗎?

          其實(shí)你在開發(fā)時(shí)不容易感覺到差別,但 React 本身是進(jìn)行了很多差別處理,如果是 Class 類,React 會(huì)用 new 關(guān)鍵字實(shí)例化,然后調(diào)用該實(shí)例的 render 方法,如果是 Func 函數(shù),React 會(huì)直接調(diào)用它。

          Refs

          如果你是一個(gè) jQuery 轉(zhuǎn)型 React 的開發(fā),會(huì)很自然的想到,我找到 Loading 組件的節(jié)點(diǎn),控制他的顯示與隱藏,當(dāng)然這也是可以的,React 提供 Refs 方便你訪問 DOM 節(jié)點(diǎn) 或 React 元素。

          export?default?class?extends?Component?{
          ??componentDidMount()?{
          ????fetch().then(()?=>?{
          ??????this.el.changeLoading(false);
          ????});
          ??}

          ??render()?{
          ????return?(
          ??????<Loading?ref={el?=>?{?this.el?=?el;?}}?/>
          ????);
          ??}
          }

          完整演示

          https://codesandbox.io/s/ywwmm3j46z

          通用邏輯抽離

          當(dāng)你的應(yīng)用做到一定的復(fù)雜度,不同的頁面都會(huì)有 loading 效果,你肯定不希望每個(gè)頁面都重復(fù)的書寫一樣的邏輯,這樣會(huì)導(dǎo)致你的代碼重復(fù)且混亂。

          React 中有兩個(gè)比較常見的解決方案 HOCRender Props,其實(shí)這兩個(gè)這兩個(gè)概念都是不依賴 React 的。

          讓我們暫時(shí)忘掉 React,下面我對 HOCRender Props 寫兩個(gè)例子,你會(huì)發(fā)現(xiàn)組件復(fù)用是如此簡單。

          HOC

          HOC 其實(shí)就是一種裝飾器模式,它接受一個(gè)組件作為參數(shù),然后返回相同的組件,這樣就可以額外增加一些功能。

          const?func?=?()?=>?{
          ??console.log("func");
          };

          const?wrap?=?func?=>?{
          ??console.log("wrap");
          ??return?func;
          };

          //?wrap?邏輯已被復(fù)用
          wrap(func)();

          完整演示

          https://codesandbox.io/s/8zx85nrzk2

          Render Props

          Render Props 就是我們給一個(gè)函數(shù)傳遞一個(gè)回調(diào)函數(shù)做為參數(shù),該回調(diào)函數(shù)就能利用外面函數(shù)的執(zhí)行結(jié)果做為參數(shù),執(zhí)行任何操作。

          const?func?=?param?=>?{
          ??console.log("func");
          };

          const?wrap?=?(param,?func)?=>?{
          ??console.log("wrap");
          ??func(param);
          };

          //?wrap?邏輯已被復(fù)用
          wrap("",?func);

          完整演示

          https://codesandbox.io/s/0v1p4rp7xv

          相同點(diǎn):

          • 兩者都能很好的幫助我們重用組件邏輯;
          • 和回調(diào)函數(shù)類似,當(dāng)嵌套層數(shù)很多時(shí),會(huì)造成回調(diào)地獄。

          不同點(diǎn):

          • HOC 和 父組件有相同屬性名屬性傳遞過來,會(huì)造成屬性丟失;
          • Render Props 你只需要實(shí)例化一個(gè)中間類,而 HOC 你每次調(diào)用的地方都需要額外實(shí)例化一個(gè)中間類。

          總的來說,在需要復(fù)用組件邏輯的時(shí)候,我個(gè)人更傾向于 Render Props 的方式。

          復(fù)雜狀態(tài)管理

          當(dāng)你的應(yīng)用越來越大,組件之間交互越來越復(fù)雜,那整個(gè)頁面的數(shù)據(jù)邏輯將變得難以管理,這時(shí)候?yàn)榱朔奖愎芾響?yīng)用的狀態(tài),你可以選擇一些狀態(tài)管理工具,例如 Redux、Flux、dva 等。

          Redux

          我不太想談這些數(shù)據(jù)流框架,因?yàn)樗麄兊母拍?action、store、dispatch 太過于生澀難懂。

          現(xiàn)代前端框架 React 和 Vue 其實(shí)都是一個(gè)套路,通過數(shù)據(jù)渲染試圖,然后視圖上操作反過來更新數(shù)據(jù),重新渲染視圖,刷新頁面。數(shù)據(jù)叫做 store,動(dòng)作叫做 ation,觸發(fā)行為叫 dispatch,然后數(shù)據(jù)到視圖的渲染由 React/Vue 處理的。

          (圖片來自 這里)

          //?reducers.js
          const?initialState?=?{
          ??loading:?false
          };

          export?default?function?reducer(state?=?initialState,?action)?{
          ??switch?(action.type)?{
          ????case?"CHANGE_LOADING":
          ??????return?{
          ????????loading:?action.payload
          ??????};
          ????default:
          ??????return?state;
          ??}
          }

          完整演示

          https://codesandbox.io/s/94zoy50q6w

          Saga

          當(dāng)你代碼中有大量的異步操作時(shí),例如 fetch 請求,你肯定會(huì)想到事件監(jiān)聽、回調(diào)函數(shù)發(fā)布/訂閱。很好,上一個(gè)例子其實(shí)就是事件監(jiān)聽的處理方式,然后回調(diào)函數(shù)的主流的解決方案是 redux-thunk,而發(fā)布/訂閱的主流解決方案是 saga。

          import?{?takeLatest,?put?}?from?"redux-saga/effects";

          import?fetch?from?"./fetch";

          function*?fetchInfo(action)?{
          ??yield?put({
          ????type:?"CHANGE_LOADING",
          ????payload:?true
          ??});

          ??yield?fetch();

          ??yield?put({
          ????type:?"CHANGE_LOADING",
          ????payload:?false
          ??});
          }

          export?default?function*?fetchSaga()?{
          ??yield?takeLatest("FETCH_REQUEST",?fetchInfo);
          }

          完整演示

          https://codesandbox.io/s/rrnp9vk3wp

          當(dāng)你耐心看到這里,我知道你對 React 肯定有一定的經(jīng)驗(yàn),現(xiàn)在還可以做很多,例如把 loading 狀態(tài)提升到 Store 的頂部,那整個(gè)站點(diǎn)就只有一個(gè) loading 了,然后你還可以將 fetch 再封裝一個(gè) HOC 修改 loading 狀態(tài),這就是一個(gè)相對完美的 loading,其實(shí) React 業(yè)務(wù)開發(fā)都可以用這個(gè)套路。

          新的 API

          Context

          上面 redux 的例子是不是過于復(fù)雜對于簡單的業(yè)務(wù),雖然有很多頁面,嵌套層次也很復(fù)雜,你當(dāng)然可以不用狀態(tài)管理工具,你可以試著使用 Context,它可以方便你傳遞數(shù)據(jù),它其實(shí)就是 Render Props 的一種實(shí)現(xiàn)。

          export?default?React.createContext({
          ??loading:?false,
          ??changeLoading:?()?=>?{}
          });

          完整演示

          https://codesandbox.io/s/6lp0p7z4jz

          Hooks

          寫到這,靜一下,是不是哪里做錯(cuò)了什么?

          我的業(yè)務(wù)只是想寫個(gè)簡單的 loading 效果,卻了解了一堆組件生命周期的概念。

          Hooks 剛好幫你解決了這樣的問題,Hooks 能允許你通過執(zhí)行單個(gè)函數(shù)調(diào)用來使用函數(shù)中的 React 功能,讓你把面向生命周期編程變成面向業(yè)務(wù)邏輯編程。

          import?React,?{?useState,?useEffect?}?from?"react";

          import?Loading?from?"./Loading/index";
          import?fetch?from?"./fetch";

          function?App()?{
          ??const?[loading,?setLoading]?=?useState(true);

          ??useEffect(()?=>?{
          ????fetch().then(()?=>?{
          ??????setLoading(false);
          ????});
          ??},?[]);

          ??return?<Loading?loading={loading}?/>;
          }

          export?default?App;

          完整演示

          https://codesandbox.io/s/98m4j00vwo

          好好總結(jié)

          上面對每個(gè)點(diǎn)都做了具體實(shí)現(xiàn),但他們都不是隔離的,你可以根據(jù)你的認(rèn)知和業(yè)務(wù)特點(diǎn)總結(jié)抽象一套自己的方法論;

          多了解、多抽象、多思考,練就十八般武藝,遇到問題的時(shí)候才能游刃有余;

          React 現(xiàn)在宣傳的東西越來越多,你最好先深入了解他們,然后用批判的眼光,保持理智,防止自己每天用很新的特性重構(gòu)你自己的代碼。

          參考文章

          React 官網(wǎng):https://reactjs.org/

          When do I know I’m ready for Redux?:https://medium.com/dailyjs/when-do-i-know-im-ready-for-redux-f34da253c85f

          文章可隨意轉(zhuǎn)載,但請保留此 原文鏈接。非常歡迎有激情的你加入 ES2049 Studio,簡歷請發(fā)送至 caijun.hcj(at)alibaba-inc.com 。

          1. JavaScript 重溫系列(22篇全)
          2. ECMAScript 重溫系列(10篇全)
          3. JavaScript設(shè)計(jì)模式 重溫系列(9篇全)
          4.?正則 / 框架 / 算法等 重溫系列(16篇全)
          5.?Webpack4 入門(上)||?Webpack4 入門(下)
          6.?MobX 入門(上)?||??MobX 入門(下)
          7. 80+篇原創(chuàng)系列匯總

          回復(fù)“加群”與大佬們一起交流學(xué)習(xí)~

          點(diǎn)擊“閱讀原文”查看 80+ 篇原創(chuàng)文章

          瀏覽 63
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  天天草人人草 | 久久久波多野结衣 | 牛牛精品一区二区 | 91另类视频 | 一区二区三区四区五区在线 |