從 loading 的 9 種寫法談 React 業務開發

banner

前言

這是一篇比較全面講解 React 的文章,裏面不少基礎知識但願你本身一邊查閱資料一邊學習。全文從業務開發中最經常使用見 loading 效果不一樣是實現講起,說下如今前端開發在業務上應該有的思考。html

入門級操做

State

最簡單的實現,咱們在 Loading 組件內部聲明一個狀態,經過代碼邏輯判斷 loading 效果的展現。前端

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

完整演示react

Props

隨着業務的發展,這個 Loading 組件用到的地方會很是多,上面這個代碼耦合了不少邏輯,爲了讓這個組件可以很好的複用,那咱們抽離出組件的業務邏輯,將內部狀態進行提高,那這個組件就是一個能被複用的 UI 組件。git

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

完整演示github

注:上面兩段代碼你可能會想,爲何 FuncClass 都能實現一個組件,他們有什麼差異嗎?
其實你在開發時不容易感受到差異,但 React 自己是進行了不少差異處理,若是是 Class 類,React 會用 new 關鍵字實例化,而後調用該實例的 render 方法,若是是 Func 函數,React 會直接調用它。編程

Refs

若是你是一個 jQuery 轉型 React 的開發,會很天然的想到,我找到 Loading 組件的節點,控制他的顯示與隱藏,固然這也是能夠的,React 提供 Refs 方便你訪問 DOM 節點 或 React 元素。redux

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

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

完整演示前端框架

通用邏輯抽離

當你的應用作到必定的複雜度,不一樣的頁面都會有 loading 效果,你確定不但願每一個頁面都重複的書寫同樣的邏輯,這樣會致使你的代碼重複且混亂。框架

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

讓咱們暫時忘掉 React,下面我對 HOCRender Props 寫兩個例子,你會發現組件複用是如此簡單。

HOC

HOC 其實就是一種裝飾器模式,它接受一個組件做爲參數,而後返回相同的組件,這樣就能夠額外增長一些功能。

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

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

// wrap 邏輯已被複用
wrap(func)();

完整演示

Render Props

Render Props 就是咱們給一個函數傳遞一個回調函數作爲參數,該回調函數就能利用外面函數的執行結果作爲參數,執行任何操做。

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

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

// wrap 邏輯已被複用
wrap("", func);

完整演示

相同點:

  • 二者都能很好的幫助咱們重用組件邏輯
  • 和回調函數相似,當嵌套層數不少時,會形成回調地獄

不一樣點:

  • HOC 和 父組件有相同屬性名屬性傳遞過來,會形成屬性丟失;
  • Render Props 你只須要實例化一箇中間類,而 HOC 你每次調用的地方都須要額外實例化一箇中間類。

總的來講,在須要複用組件邏輯的時候,我我的更傾向於 Render Props 的方式。

複雜狀態管理

當你的應用愈來愈大,組件之間交互愈來愈複雜,那整個頁面的數據邏輯將變得難以管理,這時候爲了方便管理應用的狀態,你能夠選擇一些狀態管理工具,例如 ReduxFluxdva 等。

Redux

Redux

我不太想談這些數據流框架,由於他們的概念 actionstoredispatch 太過於生澀難懂。
現代前端框架 React 和 Vue 其實都是一個套路,經過數據渲染試圖,而後視圖上操做反過來更新數據,從新渲染視圖,刷新頁面。
數據叫作 store,動做叫作 ation,觸發行爲叫 dispatch,而後數據到視圖的渲染由 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;
  }
}

完整演示

Saga

當你代碼中有大量的異步操做時,例如 fetch 請求,你確定會想到事件監聽回調函數發佈/訂閱
很好,上一個例子其實就是事件監聽的處理方式,而後回調函數的主流的解決方案是 redux-thunk,而發佈/訂閱的主流解決方案是 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);
}

完整演示

當你耐心看到這裏,我知道你對 React 確定有必定的經驗,如今還能夠作不少,例如把 loading 狀態提高到 Store 的頂部,那整個站點就只有一個 loading 了,而後你還能夠將 fetch 再封裝一個 HOC 修改 loading 狀態,這就是一個相對完美的 loading,其實 React 業務開發均可以用這個套路。

新的 API

Context

context

上面 redux 的例子是否是過於複雜
對於簡單的業務,雖然有不少頁面,嵌套層次也很複雜,你固然能夠不用狀態管理工具,你能夠試着使用 Context,它能夠方便你傳遞數據,它其實就是 Render Props 的一種實現。

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

完整演示

Hooks

寫到這,靜一下,是否是哪裏作錯了什麼?

個人業務只是想寫個簡單的 loading 效果,卻瞭解了一堆組件生命週期的概念。

Hooks 恰好幫你解決了這樣的問題,Hooks 能容許你經過執行單個函數調用來使用函數中的 React 功能,讓你把面向生命週期編程變成面向業務邏輯編程

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;

完整演示

好好總結

上面對每一個點都作了具體實現,但他們都不是隔離的,你能夠根據你的認知和業務特色總結抽象一套本身的方法論;

多瞭解多抽象多思考,練就十八般武藝,遇到問題的時候才能遊刃有餘;

React 如今宣傳的東西愈來愈多,你最好先深刻了解他們,而後用批判的眼光,保持理智,防止本身天天用很新的特性重構你本身的代碼。

參考文章

React 官網

When do I know I’m ready for Redux?

文章可隨意轉載,但請保留此 原文連接

很是歡迎有激情的你加入 ES2049 Studio,簡歷請發送至 caijun.hcj(at)alibaba-inc.com 。

相關文章
相關標籤/搜索