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

前言

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

入門級操做react

State編程

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

export default class extends Component {
  ...
  render() {
    return this.state.loading ?  : 
finish
;
  }
}
複製代碼

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

export default function(props) {
  return props.loading ?  : 
finish
;
}
複製代碼

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

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

export default class extends Component {
  componentDidMount() {
    fetch().then(() => {
      this.el.changeLoading(false);
    });
  }
  render() {
    return (
       { this.el = el; }} />
    );
  }
}
複製代碼

通用邏輯抽離異步

當你的應用作到必定的複雜度,不一樣的頁面都會有 loading 效果,你確定不但願每一個頁面都重複的書寫同樣的邏輯,這樣會致使你的代碼重複且混亂。 React 中有兩個比較常見的解決方案 HOC 和 Render Props,其實這兩個這兩個概念都是不依賴 React 的。 讓咱們暫時忘掉 React,下面我對 HOC 和 Render Props 寫兩個例子,你會發現組件複用是如此簡單。函數

HOC工具

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

const func = () => {
  console.log("func");
};
const wrap = func => {
  console.log("wrap");
  return func;
};
// wrap 邏輯已被複用
wrap(func)();
複製代碼

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 的方式。

複雜狀態管理

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

我不太想談這些數據流框架,由於他們的概念 action、store、dispatch 太過於生澀難懂。 現代前端框架 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;
  }
}
複製代碼

當你代碼中有大量的異步操做時,例如 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

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

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

複製代碼

寫到這,靜一下,是否是哪裏作錯了什麼? 個人業務只是想寫個簡單的 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 ;
}
export default App;
複製代碼

好好總結

上面對每一個點都作了具體實現,但他們都不是隔離的,你能夠根據你的認知和業務特色總結抽象一套本身的方法論; 多瞭解、多抽象、多思考,練就十八般武藝,遇到問題的時候才能遊刃有餘; React 如今宣傳的東西愈來愈多,你最好先深刻了解他們,而後用批判的眼光,保持理智,防止本身天天用很新的特性重構你本身的代碼。

轉載地址: www.yuque.com/es2049/blog…
相關文章
相關標籤/搜索