Redux介紹

Redux中主要由三部分組成:Action,Reducer,Store.


Paste_Image.png

Action

Action用來傳遞操作state的信息到store,是store的唯一來源。以對象形式存在

{ 
  type: 'ADD_TODO',//type必須驰贷,其余字段隨意崎淳。
   text: 'Build my first Redux app'
}

多數(shù)情況下,type會被定義成字符串常量秦士。且當應用規(guī)模較大時频鉴,建議使用單獨的模塊或文件來存放 action栓辜。

隨著代碼的增多,這種直接聲明方式會難以組織垛孔,可以通過Action創(chuàng)建函數(shù)(Action Creator)來生產(chǎn)action

function addTodo(text) { 
  return {
     type: 'ADD_TODO', 
     text 
  }
}

Reducer

Reducer用來處理action,通過傳入舊的state和action來指明如何更新state藕甩。

state 默認情況下要返回應用的初始 state,而且當action.type很多時周荐,reducer也可以拆分成一個個小的reducer,每個reducer分別處理state中的一部分數(shù)據(jù)狭莱,最后將處理后的數(shù)據(jù)合并成整個state。其中概作,redux提供了combineReducers()方法來合并多個子reducer腋妙。

import { combineReducers } from 'redux'
import { ADD_TODO, TOGGLE_TODO, SET_VISIBILITY_FILTER, VisibilityFilters } from './actions'
const { SHOW_ALL } = VisibilityFilters
function visibilityFilter(state = SHOW_ALL, action) {
   switch (action.type) {
     case SET_VISIBILITY_FILTER: 
        return action.filter
       default: return state 
   }
}
function todos(state = [], action) { 
    switch (action.type) { 
        case ADD_TODO:
           return [ ...state, { text: action.text, completed: false } ]
       case TOGGLE_TODO: 
            return state.map((todo, index) => {
                 if (index === action.index) { 
                      return Object.assign({}, todo, { 
                            completed: !todo.completed 
                      })
                 }
                 return todo
           })
       default: return state
 }}
const todoApp = combineReducers({ visibilityFilter, todos})
export default todoApp

Store

action用來描述發(fā)發(fā)生了什么,reducer根據(jù)action更新state,Store就是把這幾樣東西連接到一起的對象讯榕。
有以下職責:
1骤素、維持應用的state
2、提供getState()方法獲取state
3愚屁、提供dispatch()方法更新state
4济竹、通過subscribe()注冊監(jiān)聽器
5、通過subscribe()返回的函數(shù)注銷監(jiān)聽器

Redux 應用只有一個單一的 store霎槐。

import { createStore } from 'redux'
import todoApp from './reducers'
//已有的 reducer 來創(chuàng)建 store
let store = createStore(todoApp,window.STATE_FROM_SERVER)//第二個參數(shù)用于設置state初始狀態(tài)送浊。

最常用的是dispatch()方法,這是修改state的唯一途徑栽燕。Redux 中只需把 action 創(chuàng)建函數(shù)的結(jié)果傳給 dispatch()方法即可發(fā)起一次 dispatch 過程(這個過程就執(zhí)行了當前的reducer)罕袋。

dispatch(addTodo(text))
dispatch(completeTodo(index))

或者創(chuàng)建一個 被綁定的 action 創(chuàng)建函數(shù) 來自動 dispatch:

const boundAddTodo = (text) => dispatch(addTodo(text))
const boundCompleteTodo = (index) => dispatch(completeTodo(index))

然后直接調(diào)用它們:

boundAddTodo(text);
boundCompleteTodo(index);

下面是dispatch得部分源碼

function dispatch(action) { 
   currentState = currentReducer(currentState, action);
   listeners.slice().forEach(function (listener) {
       return listener(); 
   });
    return action;
}

所以redux的具體流程圖如下


redux flow

那么redux中到底數(shù)據(jù)怎么傳遞呢改淑?組件一級級的怎么通信呢?

react-redux

這用來結(jié)合react和redux浴讯,并提供了兩個接口Provider()和connect().

Provider可以將從createStore返回的store放入context中朵夏,使子集可以獲取到store并進行操作;

//將根組件包裝進Provider
let store = createStore(todoApp);
let rootElement = document.getElementById('root')
render(
  <Provider store={store}> 
        <App /> 
  </Provider>, 
  rootElement
)

connect 會把State和dispatch轉(zhuǎn)換成props傳遞給子組件, 是React與Redux連接的核心榆纽。
任何一個從 connect()包裝好的組件都可以得到一個dispatch()方法作為組件的 props仰猖,以及得到全局 state 中所需的任何內(nèi)容。connect()的唯一參數(shù)是 selector奈籽。此方法可以從 Redux store 接收到全局的 state饥侵,然后返回組件中需要的 props。

import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { addTodo, completeTodo, setVisibilityFilter, VisibilityFilters } from '../actions';
import AddTodo from '../components/AddTodo';
import TodoList from '../components/TodoList';
import Footer from '../components/Footer';
class App extends Component {
    render() {
        // 通過調(diào)用 connect() 注入dispatch()方法和兩個組件分別所需要的state
        const { dispatch, visibleTodos, visibilityFilter } = this.props
        return ( 
            < div >
                < AddTodo onAddClick = {//onAddClick是在AddToDo組件中定義的從prop繼承的屬性方法dispatch()
                    text => dispatch(addTodo(text))//向dispatch()方法傳入action衣屏,直接更新對應的state
                }
                />  
                < TodoList todos = { visibleTodos }//向該組件傳遞state
                onTodoClick = { index => dispatch(completeTodo(index)) }
                / > 
                < Footer filter = { visibilityFilter }
                onFilterChange = { nextFilter => dispatch(setVisibilityFilter(nextFilter)) }
                /> 
            </div > 
        )
    }
}
//提供驗證器躏升,來驗證傳入數(shù)據(jù)的有效性
App.propTypes = { 
    visibleTodos: PropTypes.arrayOf(PropTypes.shape({ text: PropTypes.string.isRequired, completed: PropTypes.bool.isRequired })), 
    visibilityFilter: PropTypes.oneOf(['SHOW_ALL', 'SHOW_COMPLETED', 'SHOW_ACTIVE']).isRequired }
//根據(jù)用戶選擇,從而傳入相對應的數(shù)據(jù)
function selectTodos(todos, filter) {
    switch (filter) {
        case VisibilityFilters.SHOW_ALL:
            return todos;
        case VisibilityFilters.SHOW_COMPLETED:
            return todos.filter(todo => todo.completed);
        case VisibilityFilters.SHOW_ACTIVE:
            return todos.filter(todo => !todo.completed);
    }
} 
// 基于全局 state 狼忱,哪些是我們想注入的 props ?// 注意:使用 https://github.com/faassen/reselect 效果更佳膨疏。
function select(state) {
  return {
    visibleTodos: selectTodos(state.todos, state.visibilityFilter),
    visibilityFilter: state.visibilityFilter
  };
}

// 包裝 component ,注入 dispatch 和 state 到其默認的 connect(select)(App) 中钻弄;
export default connect(select)(App);

【參考】

chrome擴展Redux Devtools
http://www.reibang.com/p/3334467e4b32
http://react-china.org/t/redux/2687
https://leozdgao.me/reacthe-reduxde-qiao-jie-react-redux/
https://github.com/matthew-sun/blog/issues/18
http://book.apebook.org/boyc/redux/redux2.html
http://hustlzp.com/post/2016/03/react-redux-deployment

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末佃却,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子窘俺,更是在濱河造成了極大的恐慌饲帅,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,423評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瘤泪,死亡現(xiàn)場離奇詭異灶泵,居然都是意外死亡,警方通過查閱死者的電腦和手機均芽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,147評論 2 385
  • 文/潘曉璐 我一進店門丘逸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來单鹿,“玉大人掀宋,你說我怎么就攤上這事≈俪” “怎么了劲妙?”我有些...
    開封第一講書人閱讀 157,019評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長儒喊。 經(jīng)常有香客問我镣奋,道長,這世上最難降的妖魔是什么怀愧? 我笑而不...
    開封第一講書人閱讀 56,443評論 1 283
  • 正文 為了忘掉前任侨颈,我火速辦了婚禮余赢,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘哈垢。我一直安慰自己妻柒,他們只是感情好,可當我...
    茶點故事閱讀 65,535評論 6 385
  • 文/花漫 我一把揭開白布耘分。 她就那樣靜靜地躺著举塔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪求泰。 梳的紋絲不亂的頭發(fā)上央渣,一...
    開封第一講書人閱讀 49,798評論 1 290
  • 那天,我揣著相機與錄音渴频,去河邊找鬼芽丹。 笑死,一個胖子當著我的面吹牛卜朗,可吹牛的內(nèi)容都是我干的志衍。 我是一名探鬼主播,決...
    沈念sama閱讀 38,941評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼聊替,長吁一口氣:“原來是場噩夢啊……” “哼楼肪!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起惹悄,我...
    開封第一講書人閱讀 37,704評論 0 266
  • 序言:老撾萬榮一對情侶失蹤春叫,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后泣港,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體暂殖,經(jīng)...
    沈念sama閱讀 44,152評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,494評論 2 327
  • 正文 我和宋清朗相戀三年当纱,在試婚紗的時候發(fā)現(xiàn)自己被綠了呛每。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,629評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡坡氯,死狀恐怖晨横,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情箫柳,我是刑警寧澤手形,帶...
    沈念sama閱讀 34,295評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站悯恍,受9級特大地震影響库糠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜涮毫,卻給世界環(huán)境...
    茶點故事閱讀 39,901評論 3 313
  • 文/蒙蒙 一瞬欧、第九天 我趴在偏房一處隱蔽的房頂上張望贷屎。 院中可真熱鬧,春花似錦艘虎、人聲如沸豫尽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽美旧。三九已至,卻和暖如春贬墩,著一層夾襖步出監(jiān)牢的瞬間榴嗅,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,978評論 1 266
  • 我被黑心中介騙來泰國打工陶舞, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留嗽测,地道東北人。 一個月前我還...
    沈念sama閱讀 46,333評論 2 360
  • 正文 我出身青樓肿孵,卻偏偏與公主長得像唠粥,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子停做,可洞房花燭夜當晚...
    茶點故事閱讀 43,499評論 2 348

推薦閱讀更多精彩內(nèi)容