十分鐘上手 React+MirrorX,從此前端大神代碼不再難懂

十分鐘上手 React+MirrorX,從此前端大神代碼不再難懂 | 原力計劃

作者 | 楊若瑜

來源 | CSDN博客,責編 | 夕顏

頭圖 | 付費下載自視覺中國

出品 | CSDN(ID:CSDNnews)

隨著React的普及,很多大廠的前端必備React相關知識,甚至已有成熟框架應用在生產環境。今天我們探討的是React進階者經常會遇到的MirrorX編寫問題,看著前人寫的組件,繞著繞著就繞糊塗了。真實案例:可能為了改一個簡單的傳參,前端開發工程師會耗費在跟代碼至少4-5個小時。因此我便做此文,用以幫助正在進階過程中的前端工程師們快速理解一個RESTful請求是怎麼經過MirrorX的處理,到達組件並激發組件重新渲染。此文大廠前端開發必備。

適合讀者:具備React基礎的程序員、用友UCF開發者、螞蟻金服Antd開發者。

十分钟上手 React+MirrorX,从此前端大神代码不再难懂 | 原力计划

概念問答

1、什麼是MirrorX?

MirrorX是基於Redux封裝的一種狀態機。比如實際使用的時候假設我們要從後臺讀個商品接口、把接口返回的數據做一些處理(比如打折的要前端計算折扣金額),然後將處理好的數據顯示在界面上。想想就得用很多代碼,而且都要放在組件的類裡吧?

要是有一個框架,組件裡只需要調一行代碼就能解決,是不是很不錯?MirrorX就是用來做這件事的。

2、怎麼能做到1行解決?

學過面向對象編程的,應該都知道封裝性可以使控制層代碼更加簡練。但是React裡如果要處理剛才說的那件事,既需要state和props控制權,也要知道來來往往的上下文(比如當前用戶是誰、VIP等級是多少),最令React程序員難受的是,當前用戶信息在UserView組件裡,當前的GoodsView組件沒有對UserView組件的訪問權。因此,需要有一個統一的地方來跨越組件的障礙,存儲這些信息,把這個機制封裝好了,就可以實現一行解決。

3、具體是怎樣的機制?

網上有很多文章講Redux,看完Redux,再搜索MirroX就可以知道具體的機制。簡單的來說,就是系統有若干個狀態倉庫,我們可以把上下文變量都分門別類放在不同倉庫裡,比如用戶信息、商品信息;放入的時候都是調用動作來實現,比如讀取商品信息、更改商品數量。而動作可以選擇是否調用服務,如果前臺更改商品數量,直接改狀態倉庫裡的數值即可,無需調用服務;如果調用了服務,則一般來說是功能是需要服務器交互的。

十分钟上手 React+MirrorX,从此前端大神代码不再难懂 | 原力计划

如何用MirrorX完成一個功能

這裡舉個請求後臺讀取商品列表的例子

1、環境準備

先確保你已經通過npm i安裝了mirrorx、react、axios。因為本文是最佳實踐,對於如何安裝不做贅述。

2、寫一個簡單的服務(Service)

寫一個service.js文件(註釋多,代碼其實沒幾行)

<code> 1import request from "axios";
2const URL={
3 GET_GOODS:"api/template/GetGoods" // 聲明要訪問的後臺接口地址
4}
5// 暴露出一個名為GetGoodsApi的函數,入參params是Object類型,代表提交給後臺的參數列表
6// 這個函數會返回一個Promise對象
7export const GetGoodsApi = (params) => {
8 return request(URL.GET_GOODS, {method: "post",params})
9}
10// 你還可以暴露出其他函數,一個Service可以export const多個函數
11// export const GetMember = (params) => {
12// return request(URL.GET_MEMBER, {method: "post",params})
13//}
/<code>

3、寫一個簡單的模型層(Model,包含動作和模型)

寫一個model.js(註釋多,代碼其實沒幾行)

<code> 1import { actions } from "mirrorx";
2import * as api from "./service"; // 把剛才的service.js引入進來,名稱定為api
3
4export default {
5 name: "GoodsManager", // 這裡寫的名字將會成為狀態倉庫的名稱
6 initialState: { // 這裡可以寫初始化時狀態機裡的初始狀態
7 userId: "0001"
8 },
9 // reducer:狀態機處理函數
10 reducers: {
11 // 這個updateState是默認的,它用來主動更新狀態機裡的各種狀態
12 // state和data都是Object對象
13 // state是框架傳入的,開發者調用的時候,data才是對應的第一個參數
14 // ...是ES6的對象擴展運算符,後面...data會自動覆蓋...state的同名屬性
15 updateState: (state, data) => ({ ...state, ...data })
16 // 後面還可以寫其他的reducer,切記第一個參數一定是state
17 },
18 effects: {
19 // 動作處理函數:獲取商品
20 // param是對象,getState是框架傳入的函數對象,用來方便獲取當前狀態機的狀態
21 // 開發者調用的時候,不用給getState形參賦值

22 async GetGoods(param, getState) {
23 // Promise的同步操作運算,獲取Axios返回的data
24 let { data } = await api.GetGoodsApi(param);
25 // 調用當前狀態機的updateState方法(也就是上面寫的那個函數)
26 // 由調用可見,只放了一個Object類型的參數
27 actions.GoodsManager.updateState({ goods: data.data });
28 }
29 }
30};
/<code>

4、改造組件,變成由MirrorX託管組件

第一步、在項目入口的地方添加(比如在app.js上添加在內存中創建狀態機的代碼):

<code>1// 引入MirrorX的組件
2import mirror from 'mirrorx';
3// 引入剛剛寫的model,注意路徑
4import model from './model';
5// 調用MirrorX,根據模型創建狀態機
6mirror.model(model);
/<code>

第二步、在受狀態機託管的組件上改一下代碼

<code>1// 增加對MirrorX的引用
2import {connect} from 'mirrorx';
3// 這裡面GoodsView就是當前受狀態機託管組件的class名稱,GoodsManager就是第二步裡name寫的名字
4export default connect(state => state.GoodsManager)(GoodsView);
/<code>

5、在需要調用的地方寫下如下代碼:

這裡因為GoodsView只要一加載就需要顯示商品列表,因此,我們可以把代碼寫在constructor(props)函數里:

<code>1// 組件上需要引入MirrorX的actions
2import {actions} from 'mirrorx';
3// 在constructor(props)函數里寫上以下調用即可
4actions.GoodsManager.GetGoods({
5 user:props.userId
6});
/<code>

然後render裡寫一下從props.goods(叫做goods是因為第三步GetGoods方法調用updateState方法時傳的就是goods,所以當前組件需要從props裡接)渲染界面的前端代碼,就可以開始測試了。

十分钟上手 React+MirrorX,从此前端大神代码不再难懂 | 原力计划

補充說明

狀態機裡所有的狀態值都會被自動寫在託管組件的props裡,當發生變化時,也是可以從props裡取出來,因此不要嘗試去獲取或更新組件的state。

只要狀態機裡的值變化,受到託管的組件會重新執行render方法,實現自動刷新。

實際開發時由於存在組件嵌套、組件元素屬性值與狀態機裡的狀態名稱衝突,各種疑難雜症隨之而來。介於我對於Antd、UCF等成熟框架的分析和實戰,得出一個結論,大型系統的model.js、service.js一般不會超過5個,而且大多都有命名規範。

如果是看別人的代碼,倒著按順序找一遍即可,從此前端大神的代碼不再難懂。

原文鏈接:

https://blog.csdn.net/yry0304/article/details/104853557


分享到:


相關文章: