Fork me on GitHub

redux快速入门

redux和vuex一样,当项目数据复杂时,都是用来集中管理数据的,不过redux是单向数据流绑定,这就使得redux中的store必须放到所有组件最顶层,此篇文章是在看《深入浅出react与redux》以及实战React16.4开发简书项目后的总结。

Redux的前身flux

在flux中,首先要引入Dispatcher(redux没有这个), 用以派发action,action改变view层,view层同步model数据层;flux会为每一个组件单独建立一个store,在每一个组件中初始化store,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const CounterStore = object.assign({}, EventEmitter.prototype, {
getCounterValues: function() {
return counterValues;
},
emitChange: function(){
this.emit(CHANGE_EVENT);
},
addChangeListener: function(){
this.on(CHANGE_EVENT, callback);
},
removeChangeListener: fucntion(){
this.removeListener(CHANGE_EVENT, callback);
}
})

EventEmitter是node.js中event模块的一个对象,是监听事件的一个封装,不用太追究;上面扩展了EventEmitter.prototype,给当前组件的store绑定了几个事件;初始化store之后,还要与dispatcher做联系,这时候会用到dispatcher的一个register函数,接受参数为action;

Dispatcher是唯一的,如果有很多个组件,Dispatcher与他们每一个组件都要做联系,通过waitFor函数来决定各个store之间的执行顺序,但这就是flux最大的缺点,因为如果store很多的话,依赖关系会越来越复杂,逻辑关系会难以维护。

Redux

在Redux中没有了Dispatcher的概念,store倒是有一个dispatch方法,用以来传递action给store
reduxFlow
如图,解释一下流程

  • 在组件内部会调用actionCreators,用于创建action对象,并且通过dispatch传送给store;
  • store接受到后,会交给reducer(纯函数) 处理;
  • reducer函数处理后会返回新的store状态;
  • store里的数据发生变化会自动触发视图层变化,结束;

下面会一一解释store,reducer,action如何创建,并且如何走通。
首先创建一个store文件夹,下面会有四个js,分别是

  • index.js // 作为入口,统一引入到这里
  • actionCreators.js // 用来统一创建对象
  • constants.js // 统一定义action的type,方便后期维护log
  • reducer.js // 用来处理action的纯函数

关于action

分割action为actionCreators和contants,方便管理维护

actionCreators.js

1
2
3
4
5
6
import * as constants from './constants'
// type为常量,从constants中引入,方便log
export const sayHello = (text) =>({
type: constants.SAY_HELLO,
text
})

constants.js

1
export const SAY_HELLO = 'SAY_HELLO'

这个其实还是跟vuex中action一样的,很好理解。

创建store

调用createStore创建store,参数传入处理函数reducer

1
2
3
4
5
import { createStore } from 'redux'
import reducer from './reducer.js'
// 调用createStore创建store,参数传入处理函数reducer
const store = createStore(reducer);
export default store

编写reducer

reducer默认接受state初始状态,和action对象,更改后的state

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import * as constants from './constants'
// 设置state初始值
const defaultState ={
text: ''
}
// 默认暴露一个纯函数
export default (state = defaultState, action)=> {
switch(action.type) {
case constants.SAY_HELLO:
return {...state, action.text}
default:
return state
}
}

改有的文件都已经创建好,现在就可以捋一遍

首先在组件内部,我们想要改变store里的数据,首先要引入刚刚创建好的action,调用store的dispatch方法将action传递给store;

1
2
3
4
5
6
// 引入store
import store from './store'
// 引入action
import * as actionCreators from './actionCreators'
// store.dispatch派发action
store.dispatch(actionCreators.sayHello('你好!'))

store收到action后会自动交给reducer处理,reducer根据其actionType的不同做不同的操作,并且返回更改后的st ate;

1
2
3
4
5
6
7
8
9
export default (state = defaultState, action)=> {
switch(action.type) {
case constants.SAY_HELLO:
// 扩展运算符
return {...state, action.text}
default:
return state
}
}

组件内部通过store.subscribe()的方法能够监听store的变化,store一旦变化就可以调用store.getState()替换当前组件的store;

1
2
3
4
5
6
7
8
// store数据变化后触发 handleCHange函数
store.subscribe(this.handleCHange)
// handleCHange函数 替换组件内部store数据
handleCHange() {
store.setState({
store.getState()
})
}

store里面的数据必须用setState更改,setState可以是一个对象,也可以是一个函数,return一个对象,后一种写法推荐,因为官网就是这么写的。
数据更新那么视图层就会自动更新,结束。

React-Redux

在react中有为react量身定做的react-redux库,其用法也有一些细微差别

react-redux自带的provider组件

1
2
3
<Provider store={store}>
<Hello/>
</Provider>

从组件根部传入store,在其所有子组件中都可以使用,具体如下:

1
2
3
4
5
6
7
8
9
10
11
12
const mapStateProps = (state) =>({
text: state.text
})
const mapDispathProps = (dispath) =>{
return {
changeText() {
//这里dispatch一个action
}
}
}
// 通过connect连接当前组件
export default connect(mapStateProps, mapDispathProps)(Hello)

  • mapStateProps:顾名思义就是将state当作props传入当前组件;
  • mapDispathProps:这个就是将Dispatch当作props传入组件;
  • 这两个需要在组件外定义,然后当作参数传入connect中;

combineReducers

一般一个组件都会定义一个store,那么多的store,里面有那么多的reducer.js,我们可以用combineReducer来合并;

1
2
3
4
5
import { combineReducers } from 'redux'
import { reducer as homeReducer } from '../store'
const reducer = combineReducers({
header: homeReducer // 可以为每一个reducer取一个名字
})

那么我们在组件获取状态时也要加上名字,改成如下:

1
2
3
const mapStateProps = (state) =>({
text: state.header.text
})

快速开始模板

Github: https://github.com/mywebc/react_start

-------------本文结束感谢您的阅读-------------

本文标题:redux快速入门

文章作者:陈晓拉尼

发布时间:2018年08月29日 - 23:08

最后更新:2018年10月07日 - 22:10

原始链接:http://yoursite.com/archives/50627.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。