摘要:但是把這些組件串起來也有很多邏輯,如果每個類似的模塊都重復(fù)寫,任何一個小的邏輯發(fā)生變化,都可能需要修改所有的模塊實現(xiàn)。接下來我們是的類似的,也是通過和來唯一地標識一個模塊。當(dāng)然每個模塊可能會有不同的,這個也可以通過的入?yún)碓O(shè)置。
我們開發(fā)一個新產(chǎn)品的時候,通常會先抽象出一些公用的組件,然后通過這些組件來拼裝成頁面。不知道大家有沒有發(fā)現(xiàn),這種開發(fā)方式帶來的問題是一個團隊內(nèi)經(jīng)常會有這樣的場景:
A 已經(jīng)開發(fā)了一個 XX 表格模塊,B 要開發(fā)一個類似的 YY 表格模塊,然后 B 通常是去把 A 的代碼 copy 一下,修改一些東西;或者不巧 B 不知道 A 已經(jīng)開發(fā) XX 表格,然后 B 又得一行行的寫一些類似的代碼。
造成這種問題的原因簡單的說就是:組件抽象的粒度太單一。接下來我們會通過兩個例子來講述問題及我們?nèi)绾谓鉀Q這樣的問題的。
一個簡單的組件 - Switch首先我們看一個簡單的 Switch 組件,如果一個產(chǎn)品中有常用的兩種切換功能:
如果使用之前封裝的基礎(chǔ)組件組件 Switch 來實現(xiàn),我們需要如下調(diào)用:
趨勢 列表
這種組件抽象方式(實現(xiàn)省略)好處就是通用性強,但帶來一些問題:
每個人都需要維護選項的展示名稱和順序之間的關(guān)系
調(diào)用代碼較長,有冗余
于是,我們對這類組件進行了重構(gòu),希望讓每個組件使用更加簡單,只需要關(guān)系具體的狀態(tài)即可。具體的做法就是開發(fā)一個 Generator —— generateSwitch 來生成常用的切換組件:
export const generateSwitch = (name, options) => {
const propTypes = {
className: PropTypes.string,
activeKey: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
onChange: PropTypes.func.isRequired,
};
const Switch = (props) => {
...
return (
{
options.map((entry, index) => (
...
))
}
);
};
Switch.propTypes = propTypes;
Switch.displayName = name;
return Switch;
};
export const ASwitch = generateSwitch("ABSwitch", [
{ name: "AA", key: "a" },
{ name: "BB", key: "b" },
]);
export const BSwitch = generateSwitch("CDSwitch", [
{ name: "CC", key: "c" },
{ name: "DD", key: "d" },
]);
這種做法就可以解決上面說的問題:
比常見的切換組件使用更加便利,調(diào)用代碼一行就夠了,而且能夠起到統(tǒng)一參數(shù)的作用;
對外暴露生成函數(shù) generateSwitch 也能保證通用性。
更復(fù)雜的例子 - 業(yè)務(wù)模塊下面以一個表格業(yè)務(wù)為例,常見的表格模塊如下:
在開發(fā)這個模塊的時候,雖然每個小區(qū)塊我們都抽取了相應(yīng)的組件,如 Selector, Table, Switch, Pagination 等。但是把這些組件串起來也有很多邏輯,如果每個類似的模塊都重復(fù)寫,任何一個小的邏輯發(fā)生變化,都可能需要修改所有的模塊實現(xiàn)。所以這時候我們想做的事情就是:這個模塊本身也是一個組件,我們只需要通過一些配置生成不同的模塊,而不是重復(fù)的 copy 代碼,然后修改一些差異的地方。
在這里碰到的一個問題是,我們整個系統(tǒng)是使用 Redux 來管理數(shù)據(jù)的,整個項目的 Store 結(jié)構(gòu)如下:
每個業(yè)務(wù)模塊會去 connect 相應(yīng)的數(shù)據(jù)以及 actions ,每個模塊都有相應(yīng)的 reducer。并且每個卡片的 action 也需要做到全局唯一,所以我們給模塊的 UI Component 以及 reducer 分別開發(fā)了相應(yīng)的 Generator。
首先來看 UI Component 的 Generator:
function generateAbcModule({pageName, moduleName}) { const ACTION_PREFIX = `${pageName}/${moduleName}`; const LOAD = ACTION_PREFIX + "LOAD"; ... function load(url, params, id) { return (dispatch, getState) => { const state = getState(); ... return dispatch({ type: LOAD, .... }); }; } @connect((state, props) => { const moduleState = state[pageName][moduleName]; return { ...moduleState, }; }, { load, }) class AbcModule extends Component { ... } return AbcModule; }
通過代碼發(fā)現(xiàn),我們把 actionCreators 與 UI 放在了一起,然后通過 pageName 和 moduleName 來唯一地標識一個模塊,拼裝這兩個參數(shù)作為 action 的前綴,從而達到每個模塊的 action 是全局唯一的。
接下來我們是 reducer 的 Generator:
function generateAbcModuleReducer({pageName, moduleName, defaultIndexes}) { const ACTION_PREFIX = `${pageName}/${moduleName}/`; const LOAD = ACTION_PREFIX + "LOAD"; const initialState = { indexes: defaultIndexes, ... }; return function AbcModuleReducer(state = initialState, action) { switch (action.type) { case LOAD: return { ...state, isLoading: true, ... }; ... } };
類似的,reducer Generator 也是通過 pageName 和 moduleName 來唯一地標識一個模塊。當(dāng)然每個模塊可能會有不同的 initialState,這個也可以通過 generateAbcModuleReducer 的入?yún)碓O(shè)置。
總結(jié)上面這種使用 Generator 來封裝業(yè)務(wù)模塊的方法,能夠在一定程度上減少重復(fù)代碼,加快開發(fā)速度,不過如果業(yè)務(wù)發(fā)展的很快,有可能會導(dǎo)致業(yè)務(wù)模塊組件 props 泛濫 的問題。
以上面的排行卡片為例,可變的東西就非常多,相應(yīng)的就需要很多的 props 來配置,所以我們也需要根據(jù)具體的業(yè)務(wù)來把握是否要進行抽象。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/79720.html
摘要:精讀源碼一共行,我們分析一下其精妙的方式。更多討論討論地址是精讀新用法如果你想?yún)⑴c討論,請點擊這里,每周都有新的主題,周末或周一發(fā)布。前端精讀幫你篩選靠譜的內(nèi)容。 1 引言 很高興這一期的話題是由 epitath 的作者 grsabreu 提供的。 前端發(fā)展了 20 多年,隨著發(fā)展中國家越來越多的互聯(lián)網(wǎng)從業(yè)者涌入,現(xiàn)在前端知識玲瑯滿足,概念、庫也越來越多。雖然內(nèi)容越來越多,但作為個體的...
摘要:后面會利用這個框架來做實踐。接下來就是我們要繼續(xù)探討的同構(gòu)同構(gòu)數(shù)據(jù)處理的探討我們都知道,瀏覽器端獲取數(shù)據(jù)需要發(fā)起請求,實際上發(fā)起的請求就是對應(yīng)服務(wù)端一個路由控制器。是有生命周期的,官方給我們指出的綁定,應(yīng)該在里來進行。 眾所周知,目前的 WEB 應(yīng)用,用戶體驗要求越來越高,WEB 交互變得越來越豐富!前端可以做的事越來越多,去年 Node 引領(lǐng)了前后端分層的浪潮,而 React 的出現(xiàn)...
摘要:寫好的單元測試,對開發(fā)速度項目維護有莫大的幫助。我認為單元測試的上下文存在于敏捷中。接下來一小節(jié),就可以正式進入如何做的環(huán)節(jié)了如何寫好單元測試。前面說到,我們對單元測試寄予 寫好的單元測試,對開發(fā)速度、項目維護有莫大的幫助。前端的測試工具一直推陳出新,而測試的核心、原則卻少有變化。與產(chǎn)品代碼一并交付可靠的測試代碼,是每個專業(yè)開發(fā)者應(yīng)該不斷靠近的一個理想之地。本文就圍繞測試講講,為什么我...
摘要:盲目使用替換后可能會導(dǎo)致預(yù)期意外的結(jié)果。在中,許多種方法來處理函數(shù)的參數(shù)默認值,參數(shù)數(shù)量,參數(shù)命名。此外,處理后的值,無論是解決還是拒絕的結(jié)果值,都是不可改變的。 這是一個 ES2015(ES6) 的Cheatsheet,其中包括提示、小技巧、最佳實踐和一些代碼片段,幫助你完成日復(fù)一日的開發(fā)工作。 Table of Contents var 與 let / const 聲明 代碼執(zhí)行...
摘要:模塊化以項目中普遍會有的文件為例,實現(xiàn)導(dǎo)出再在其他文件中通過實現(xiàn)導(dǎo)入導(dǎo)入模塊使用統(tǒng)一的模塊化規(guī)范,可以提高代碼的可讀性,更易于維護。類操作先實戰(zhàn)創(chuàng)建一個類在中創(chuàng)建實例中的類能讓我們可以用更簡明的語法實現(xiàn)繼承,也使代碼的可讀性變得更高。 上一篇通過TodoList的練習(xí),目的是為了讓大家理解ES6中各種新特性的實際用途。 最好的學(xué)習(xí)方法就是實踐,所以這節(jié)課結(jié)合實際項目,來更好的理解和掌握...
閱讀 3604·2023-04-25 15:52
閱讀 643·2021-11-19 09:40
閱讀 2835·2021-09-26 09:47
閱讀 1087·2021-09-22 15:17
閱讀 3664·2021-08-13 13:25
閱讀 2382·2019-08-30 15:56
閱讀 3549·2019-08-30 13:56
閱讀 2184·2019-08-30 11:27