1. 程式人生 > >Redux架構設計融合

Redux架構設計融合

在學習react的路上不斷前行,遇到了各式各樣的框架及架構,但整體是要做一個相容性及效能非常好的專案並非易事,在react中,出現了redux生態圈,得以將react這匹黑馬駕馭得更好,此文將演示redux生態在實際專案運用。

整備

網路:axios
一個基於promise實現的網路請求庫,功能齊全,庫精簡

解放switch,程式碼更簡潔

優化reduce與渲染

可將複雜的業務邏輯非同步化

將整個store樹持久化,解放各類儲存資料

在追過藝術道路上的UI佈道者

結構

.
├── package-lock.json
├── package.json
├── public
│   ├── favicon.ico
│   ├── ico
│   │   ├── favicon.icns
│   │   ├── favicon.ico
│   │   └── favicon.png
│   └── index.html
├── src
│   ├── components
│   │   └── app.js
│   ├── config.json
│   ├── epics
│   │   ├── app.js
│   │   └── index.js
│   ├── index.js
│   ├── middles
│   │   ├── index.js
│   │   ├── log.js
│   │   └── warn.js
│   ├── reducers
│   │   ├── app.js
│   │   └── index.js
│   ├── rx
│   │   └── extends.js
│   ├── selectors
│   │   └── counter.js
│   └── store
│       └── persistor.js
└── yarn.lock
目錄 說明
src/components 存放頁面元件
epics 非同步請求或邏輯
middles 各類中介軟體
reducers redux core
rx rxjs 擴充套件方法
selectors 渲染快取或多redux共享資料
store 整合專用
  1. 專案會從src/index.js入口開始載入
  2. redux的store也是從這裡開始初始化
  3. src/store/persistor.js
    這裡的persistor我們配置非常簡單,因為我們把一些配置交給了reducers,middles,epicsindex.js去自動配置了
import {composeWithDevTools} from 'redux-devtools-extension';
# 1. 這裡使用引入redux-devtools開發者工具,用於觀察action與state樹的資訊
const epicMiddleware = createEpicMiddleware();
# 2. 例項化一個epic異常流框架
const rootEpic = combineEpics(
    ...epics
);
# 3. 接著把我們`src/epics`目錄下的所有元件組合起來
let store = createStore(
        persistedReducer,
        preloadedState,
        comp(applyMiddleware(epicMiddleware, ...middles))
    );
# 4. redux的store初始化,包括各類中介軟體
epicMiddleware.run(rootEpic);
# 5. 別忘了執行異常流處理(之前版本不用手動流行,新版本必需)
  1. src/reducers/index.js
import {enableBatching} from 'redux-batched-actions';
# 這裡引入批actions,可以同時傳送多個action,實際業務中會用到很多
import {combineReducers} from "redux";
import appReducer from "./app";

export default enableBatching(combineReducers({
    ...appReducer,
}));
  1. src/reducers/app.js
import {createActions, handleActions} from 'redux-actions';
# 去除switch,簡潔我們的程式碼,注重程式碼視覺化
import {filterActions} from 'redux-ignore';
# 增加效能,屬於自己的功能自己的處理

export const actions = createActions({
    changeText: (text) => ({text}),
    searchSuccess: (data) => ({data}),
    searchFailed: (error) => ({error}),
});

export const types = {
    changeText: 'changeText',
    search: 'search',
    searchSuccess: 'searchSuccess',
    searchFailed: 'searchFailed',
};

const defaultState = {
    name: '',
    searching: false,
    list: []
};

const reducer = handleActions({
    changeText: (state, action) => ({...state, searching: true, name: action.payload.text}),
    searchSuccess: function (state, action) {
        return {...state, list: action.payload.data.items, searching: false};
    },
    searchFailed: function (state, action) {
        return {...state, searching: false};
    },
}, defaultState);

export default {
    app: filterActions(reducer, Object.keys(actions))
};
  1. src/epics/app.js
import 'rxjs/Rx';
import '../rx/extends';
import axios from 'axios';
import {Observable} from 'rxjs/Rx';
import {types, actions} from "../reducers/app";

export const apis = {
    searchApi:(name)=>axios.get(`https://api.github.com/search/users?q=${name}`)
};

const search = action$ =>
    action$.ofType(types.changeText)
        .debounceTime(1000) //去抖動
        .switchMap(action => Observable.fromPromise(apis.searchApi(action.payload.text)))
        .retryWithDelay(3, 2000)//網路重試
        .map(response => actions.searchSuccess(response.data))
        .catch(error => Observable.of(actions.searchFailed(error)));

export default [search];
  1. src/middles/index.js
import {batchDispatchMiddleware} from 'redux-batched-actions';
import warn from './warn';
import log from './log';
# 可以引入自己的開發中間件
export default [
    batchDispatchMiddleware,
    warn,
    log
]
  1. src/selectors/counter.js
import {createSelector} from 'reselect';
# 可以用於共享多個redux的資料,在components元件中引入即可,帶快取功能,增加渲染效能
const todosSelector = (state, props) => state.yeah;
# 所有帶計算功能的這將放入這裡
const fSelector = createSelector(
    [todosSelector],
    (todos) => {
        return {
            count:Math.abs(1,2),//這裡簡單列出個別函式,一般用於大量判斷條件,比對,複製類的
            ...todos
        }
    }
);

export default fSelector;

專案開發

npm start

演示效果

這裡使用github的api搜尋使用者資訊,在1秒內多次輸入只會以最後一次為準,經典的去抖搜尋方式