## 數據流
嚴格的單向數據流是 Redux 架構的設計核心。
這意味著應用中所有的數據都遵循相同的生命周期,這樣可以讓應用變得更加可預測且容易理解。同時也鼓勵做數據范式化,這樣可以避免使用多個且獨立的無法相互引用的重復數據。
如果這些理由還不足以令你信服,讀一下 動機 和 Flux 案例,這里面有更加詳細的單向數據流優勢分析。雖然 Redux 并不是嚴格意義上的 Flux,但它們有共同的設計思想。
Redux 應用中數據的生命周期遵循下面 4 個步驟:
### 1. 調用` store.dispatch(action)`。
Action 就是一個描述“發生了什么”的普通對象。比如:
~~~
{ type: 'LIKE_ARTICLE', articleId: 42 }
{ type: 'FETCH_USER_SUCCESS', response: { id: 3, name: 'Mary' } }
{ type: 'ADD_TODO', text: 'Read the Redux docs.' }
~~~
可以把 action 理解成新聞的摘要。如 “瑪麗喜歡42號文章。” 或者 “任務列表里添加了'學習 Redux 文檔'”。
你可以在任何地方調用 `store.dispatch(action)`,包括組件中、XHR 回調中、甚至定時器中。
### 2. Redux store 調用傳入的 reducer 函數。
Store 會把兩個參數傳入 reducer: 當前的 state 樹和 action。例如,在這個 todo 應用中,根 reducer 可能接收這樣的數據:
~~~
// 當前應用的 state(todos 列表和選中的過濾器)
let previousState = {
visibleTodoFilter: 'SHOW_ALL',
todos: [
{
text: 'Read the docs.',
complete: false
}
]
}
// 將要執行的 action(添加一個 todo)
let action = {
type: 'ADD_TODO',
text: 'Understand the flow.'
}
// reducer 返回處理后的應用狀態
let nextState = todoApp(previousState, action)
~~~
注意 reducer 是純函數。它僅僅用于計算下一個 state。它應該是完全可預測的:多次傳入相同的輸入必須產生相同的輸出。它不應做有副作用的操作,如 API 調用或路由跳轉。這些應該在 dispatch action 前發生。
根 reducer 應該把多個子 reducer 輸出合并成一個單一的 state 樹。
根 reducer 的結構完全由你決定。Redux 原生提供combineReducers()輔助函數,來把根 reducer 拆分成多個函數,用于分別處理 state 樹的一個分支。
下面演示 combineReducers() 如何使用。假如你有兩個 reducer:一個是 todo 列表,另一個是當前選擇的過濾器設置:
~~~
function todos(state = [], action) {
// 省略處理邏輯...
return nextState
}
function visibleTodoFilter(state = 'SHOW_ALL', action) {
// 省略處理邏輯...
return nextState
}
let todoApp = combineReducers({
todos,
visibleTodoFilter
})
~~~
當你觸發 action 后,combineReducers 返回的 todoApp 會負責調用兩個 reducer:
~~~
let nextTodos = todos(state.todos, action)
let nextVisibleTodoFilter = visibleTodoFilter(state.visibleTodoFilter, action)
~~~
然后會把兩個結果集合并成一個 state 樹:
~~~
return {
todos: nextTodos,
visibleTodoFilter: nextVisibleTodoFilter
}
~~~
雖然 `combineReducers() `是一個很方便的輔助工具,你也可以選擇不用;你可以自行實現自己的根 reducer!
Redux store 保存了根 reducer 返回的完整 state 樹。
這個新的樹就是應用的下一個 state!所有訂閱 `store.subscribe(listener) `的監聽器都將被調用;監聽器里可以調用 store.getState() 獲得當前 state。
現在,可以應用新的 state 來更新 UI。如果你使用了 `React Redux` 這類的綁定庫,這時就應該調用 `component.setState(newState)` 來更新。
下一步
現在你已經理解了 Redux 如何工作,是時候結合 React 開發應用了。
高級用戶使用注意
如果你已經熟悉了基礎概念且完成了這個教程,可以學習高級教程中的異步數據流,你將學到如何使用 `middleware` 在 異步 action 到達 reducer 前處理它們。
- js
- js繼承
- keyCode
- 好的網站
- 零散知識點-js
- This
- 對象深拷貝和淺拷貝
- 數組方法
- 數組的深拷貝和淺拷貝
- JS 引擎的執行機制
- js中的new
- 常用正則
- 函數柯里化
- 會修改當前數組的方法
- 不會修改當前數組的方法
- 函數式編程
- 循環遍歷
- 基礎知識
- 異步
- js知識總結
- fileReader
- HTML
- 零散知識點
- html5新特性
- viewport
- CSS
- cursor
- css3新特性
- 水平居中
- 垂直居中
- display解析
- 塊級元素和行內元素
- css技巧和方法
- 清除浮動
- Less
- Sass
- 綜合
- 微信小程序
- 前端面試
- CSS-面試
- JS-面試
- js-web-api
- js知識
- MVC-面試
- jQuery與框架的區別
- 閉包
- promise
- http狀態碼
- cdn
- 離線存儲
- 事件
- web安全
- 性能優化
- 響應式
- 服務器渲染和本地渲染
- 模板是什么?
- VUE流程
- 瀏覽器渲染過程
- this的指向
- new的使用
- HTML-面試
- title和alt區別
- html5元素
- h5新特性
- 圖片格式
- 零散面試總結
- react
- 生命周期-react
- state
- props
- 組件通信
- 虛擬DOM
- 源碼分析
- webstorm-template
- element與component區別
- 組件的理解
- JXS
- vue與react區別
- 16.8版本
- vue
- 生命周期-vue
- 實現流程
- webpack
- 概念
- 入口起點
- 出口
- loader
- 模式
- 插件
- manifest
- redux
- 介紹
- 核心概念
- 三大原則
- 基礎
- action
- reducer
- store
- 數據流
- 高級
- 異步action
- 異步數據流
- middleware
- ES6阮一峰
- ...
- let
- es6箭頭函數
- const
- 塊級作用域
- 頂層對象的屬性
- global 對象
- 變量的解構賦值
- 字符串的擴展
- promise對象
- 正則的擴展
- 數值的擴展
- Math對象的擴展
- 函數的擴展
- 數組的擴展
- 對象的擴展
- symbol
- async函數
- class的基本用法
- Class 的繼承
- Set 和 Map 數據結構
- 開發工具
- 好用的軟件
- chrome插件
- 其他實用工具
- 微信公眾號-前端早讀課
- 【第1352期】map和reduce,處理數據結構的利器
- 微信公眾號-前端大全
- JS 的執行機制
- 一篇文章理解 JS 繼承
- 瀏覽器
- 緩存
- 《Webkit技術內幕》之頁面渲染過程
- 跨域
- 安全
- XSS
- 設計模式
- 發布訂閱模式
- 工廠模式
- MV*模式
- 觀察者模式
- react-router
- 一些小技巧
- js一些小算法
- 1.已知一個數組中的值,在另外一個數組中查找該值
- 累加器
- 數組隨機
- 數組扁平化并去重排序
- Immutable
- 常用命令
- hybrid
- schema封裝
- typescript