最近在學(xué)react挤渔,官方的英文文檔看起來甚是有意思,但 talk is cheap, show me the code。所以先手?jǐn)]一個 todo list骡男,后面再升級引入 react-redux,便于狀態(tài)管理傍睹。
todoList的功能如下:
(1)用戶可輸入新的內(nèi)容隔盛,點(diǎn)擊 "Add todo"添加,默認(rèn)初始狀態(tài)是未完成(incomplete)拾稳;
(2)用戶通過勾選待做事項(xiàng)前的方框吮炕,將該事項(xiàng)標(biāo)記為完成狀態(tài)(completed);
(3)用戶通過底部三個按鈕访得,可按事項(xiàng)的完成狀態(tài)分類別查看龙亲。
這個應(yīng)用麻雀雖小五臟俱全陕凹,效果圖如下。
在開始寫代碼實(shí)現(xiàn)之前鳄炉,一定要先分析好業(yè)務(wù)邏輯杜耙,再結(jié)合UI取拆分組件,尤其要考慮好 state拂盯、props 中的數(shù)據(jù)以及它們所在的組件層級佑女,要遵守 react 的設(shè)計(jì)思想。
這里定義了五個組件谈竿,TodoApp团驱、AddTodo、TodoList榕订、Todo店茶、VisibilityFilters,介紹如下:
(1)TodoApp:應(yīng)用的入口組件劫恒,層級最高贩幻,AddTodo、TodoList两嘴、VisibilityFilters 都在這里進(jìn)行渲染(render)丛楚。
(2)AddTodo:包含一個輸入框(input)和一個“Add todo ”按鈕,以便用戶添加待做事項(xiàng)(todo)憔辫。
(3)TodoList :是 Todo 組件的父級組件趣些,展示由 Todo 組件構(gòu)成的事項(xiàng)列表,不過僅展示符合 VisibilityFilters 組件中確定的當(dāng)前過濾條件的事項(xiàng)贰您。
(4)Todo:渲染單個事項(xiàng)坏平,每個事項(xiàng)內(nèi)容前面有復(fù)選框供用戶點(diǎn)擊標(biāo)記事項(xiàng)的完成狀態(tài)。
(5)VisibilityFilters:渲染決定事項(xiàng)是否顯示的過濾條件锦亦,用戶可點(diǎn)擊設(shè)置舶替。
組件的定義、功能杠园、層級關(guān)系以及用戶交互致使?fàn)顟B(tài)改變的地方都已說明完畢顾瞪,代碼較多就不貼了,要看請點(diǎn)這里
抛蚁,歡迎指正陈醒。(純手?jǐn)],只使用了 react 本身的狀態(tài)管理瞧甩、數(shù)據(jù)流動機(jī)制钉跷,未引入 redux),盡管要實(shí)現(xiàn)的功能并不復(fù)雜亲配,但是這里面的狀態(tài)管理已經(jīng)不簡單了尘应。
下面將引入redux惶凝,在借助 redux 進(jìn)行狀態(tài)管理后吼虎,組件本身的代碼就簡潔多了犬钢,因?yàn)闋顟B(tài)相關(guān)邏輯代碼被提取放置到專門的文件中,如下圖所示的 redux 文件目錄思灰。
現(xiàn)在簡要介紹下redux 部分的組織結(jié)構(gòu):
(1)Store: 可視為狀態(tài)(state)的容器玷犹,本應(yīng)用的 state 有: todos,visibilityFilters洒疚,這部分代碼很少歹颓,主要處理在 reducers 中。
(2)Action Creators:狀態(tài)(state)是通過發(fā)送(dispatch)動作(action)來間接改變的油湖,Action Creators 這部分對應(yīng) action.js 文件巍扛,用來生成動作(action),本應(yīng)用中的動作有 ADD_TODO乏德、TOGGLE_TODO撤奸、SET_FILTER,以下是 ADD_TODO 的示例喊括,addTodo 函數(shù)是 action creator胧瓜,返回的對象就是一個 action(由類型,有效內(nèi)容定義)郑什。
export const addTodo = content => ({
type: ADD_TODO,
payload: {
id: ++nextTodoId,
content
}
});
(3)Reducers:這部分用來具體規(guī)定 動作(action)如何改變 狀態(tài) (state)府喳,注意對整體狀態(tài)作劃分處理,如下 visibilityFilter reducer 只負(fù)責(zé) visibilityFilter 這部分狀態(tài)蘑拯。
const initialState = VISIBILITY_FILTERS.ALL;
const visibilityFilter = (state = initialState, action) => {
switch (action.type) {
case SET_FILTER: {
return action.payload.filter;
}
default: {
return state;
}
}
};
(4)Selectors:select from store combining information from multiple reducers钝满,比較負(fù)責(zé)的狀態(tài)數(shù)據(jù)選擇邏輯放這里會使得代碼更加清晰可維護(hù)。
通過 connect 函數(shù)讓組件與 store 連接申窘,該函數(shù)可傳入兩個可選參數(shù) mapStateToProps 和 mapDispatchToProps 弯蚜,這兩個參數(shù)的全稱很好地詮釋了它們的作用,前者是從整體 state 狀態(tài)中取出被連接的組件需要的部分(組件被動接收狀態(tài))偶洋,后者賦予組件(及其內(nèi)部子孫組件熟吏,即使子孫組件未通過 connect函數(shù)與全局 state 連接)改變 state 的能力(組件主動改變狀態(tài)),前者要傳入的部分狀態(tài)(如以下示例中的 todos)與后者要傳入的 dispatch 函數(shù)(以下示例中的 toggleTodo)玄窝,在被連接組件(TodoList)中都是通過 props 來獲取牵寺。
export default connect(
state=>({todos:getTodosByVisibilityFilter(state)}), // mapStateToProps
{toggleTodo} // mapDispatchToProps
)(TodoList)
被連接的組件(<TodoList>)在 react 組件結(jié)構(gòu)中被嵌套在 <Connect(TodoList)>組件中,在chrome中通過 React 開發(fā)者工作查看如下:
reference:
1
[2] react 官網(wǎng)文檔
[3] redux 官網(wǎng)文檔