按角色組織
如果你用MVC框架開發過應用,應該知道MVC
框架之下,通常有這樣一種程式碼組織方式:
controllers/
todoController.js
filterController.js
models/
todoModel.js
filterModel.js
views/
todo.js
todoItem.js
filter.js
Controller
、Model
、View
分別代表三種模組角色。這種組織程式碼的方式叫做“按角色組織”。
因為MVC
的影響深遠,一些風格依然影響了前端人員的思維方式,在Redux應用的構建中,就有這種組織方式:
reducers/
todoReducer.js
filterReducer.js
actions/
todoAction.js
filterActions.js
components/
todoList.js
todoItem.js
filter.js
containers/
todoListContainer.js
todoItemContainer.js
filterContainer.js
角色如下:
-
reducers
目錄包含所有Redux的reducer; -
actions
目錄包含所有action建構函式; -
components
目錄包含所有的展示元件; -
containers
目錄包含所有的容器元件。
這種按角色組織的方式看起來不錯,實際非常不利於應用的擴充套件。當你需要對一個功能進行修改時,要在多個角色目錄下切換,當功能模組多了,這種頻繁的目錄切換即浪費時間也增加了編碼厭倦感。
如果說MVC
框架下,因為三個角色之間的交叉關係,也只能默默接受,那麼在Redux
框架下,我們已經有機會實行嚴格模組化思想。
按功能組織
Redux
應用適合於“按功能組織”,也就是把完成同一應用功能的程式碼放在一個目錄下,一個應用功能包含多個角色的程式碼。Redux
中,不同的角色就是reducer
、actions
和檢視,而應用功能對應的就是使用者介面的互動模組。
拿Todo
應用來說,兩個基本的功能就是TodoList
和Filter
,所以按功能組織就是這樣子:
todoList/
actions.js
actionTypes.js
index.js
reducer.js
views/
components.js
containers.js
filter/
actions.js
actionTypes.js
index.js
reducer.js
views/
components.js
container.js
每個功能模組對應一個目錄,分別是todoList
和filter
,每個目錄下包含同樣的角色檔案:
-
actionTypes.js
定義action型別; -
actions.js
定義action建構函式; -
reducer.js
定義這個功能模組如果響應actions.js定義的動作; -
views
包含功能模組中所有的React元件,包括展示元件和容器元件; -
index.js
把所有的角色匯入,統一匯出。
這種組織方式下,當你要修改某個模組時,只要關注對應的目錄即可。
按功能組織下的每個模組,都有一個index.js,明確了模組對外的介面:
import * as actions from `./actions.js`;
import reducer from `./reducer.js`;
import view from `./views/container.js`;
export { actions, reducer, view };
當filter模組依賴todoList模組時,對應的匯入程式碼:
import { actions, reducer, view as TodoList } from `../todoList`;
混合方式
大型應用中,下面這種混合方式(既採用型別劃分的優勢,又新增了功能劃分的特點)也是不錯的選擇。
src/ 所有原始碼存放的路徑
app.js 整個應用的入口
views/ 應用中某個頁面的入口檔案,一般為路由元件
Home.js 例如,首頁的入口就是Home.js
Home.css Home頁面對應的樣式
HomeRedux.js Home頁面中所有與Redux相關的reducer、action creator的彙總,即components/Home/下所有*Redux.js的彙總
components/ 所有應用的元件
Home/ 例如,views/中一個名為Home的view,則在components/中就有一個名為Home的子資料夾
Table.js Home頁面中的一個列表元件
Table.css 列表元件對應的樣式
TableRedux.js 列表元件的reducer、action creator及action type,整合在一個檔案中
Modal.js
Modal.css
ModalRedux.js
shared/ 不歸屬於任何view的元件,如一些公共元件等
containers/
DevTools.js 配置DevTools
Root.js 一般被app.js依賴,用於根據環境判斷是否需要載入DevTools
layouts/ 佈局相關的元件及樣式,如選單、側邊欄、header、footer等
redux/ Redux store相關的配置
reducers.js 整個應用中所有reducer的彙總
routes/ 路由相關的配置
utils/ 工具函式、常量等
styles/ 全域性公共樣式
app.css 應用主樣式表
基本上,我們只需要關注的就是views/和components/這兩個目錄,它們也是存放絕大多數業務程式碼的地方。
在views/目錄中,存放的是每個路由的入口頁,如首頁(Home)、詳情頁(Detail)、管理後臺頁(Admin)等。而每個入口都會有三個檔案:.js是入口的元件,.css是對應元件的樣式,而*Redux.js是components/Home/目錄下所有reducer和action的聚合。
在components/Home/目錄裡,是當前路由對應的頁面(Home)需要的所有內容——components、actions、reducers、樣式等。
什麼是*Redux.js?實際上,按照Redux應用的一般目錄結構劃分方式,應該分別有reducers、action creator和constants資料夾。但是在實際應用中,我們發現這樣的劃分方式略顯繁瑣,新增一個元件需要至少新建4個檔案。同時對於業務應用來說,reducers等於Redux相關的檔案並不太可能被其他地方複用,因此放在一個檔案裡組織並管理是更好的選擇。目前在Redux社群中也存在一個類似的規範。Ducks modular redux