如果你是Redux入门者,建议就此打住,直接跳到文末,那里有对初学者的建议…
Github地址:https://github.com/reactjs/redux
英文原版文档地址:http://redux.js.org
在线中文文档地址:http://cn.redux.js.org
前言
Redux是一个前端库,主要是用来解决为什么要写这篇文章呢?是因为自己之前在用Redux的时候,发现花样最繁多的当属在View界面上进行的操作了。而对于单纯的前端来讲,Redux的接入和在React中接入有所不同。接下来我们介绍一下在React中使用Redux时,View中的部分逻辑。
牵线React与Redux
在单纯的前端中使用Redux时,直接使用store里的两个函数就可以实现简单的store.getState()
、store.subscribe()
以及store.dispatch(...)
几个核心函数即可完成Store
与View
的绑定和简单使用。而对于React来讲,需要使用一个中间件来实现Redux与React的无缝接入——react-redux
, 一款同样由facebook的reactjs小组开源的一个配套库。( 突然发现这篇文章应该叫做‘react-redux的使用’才对,逃~ )
使用纯Redux来实现React中的应用
和上边讲的一致,这里我讲一下具体步骤:
- 写好你的Reducer (这部分本文不做讲解)
如下是项目中reducers里index.js部分的代码import {combineReducers} from 'redux'
import viewTree from './viewTreeReducer'
export default combineReducers({
viewTree
})
上述代码的作用,就是通过combineReducer函数将多个reducers进行合并然后导出之。至于文件名叫index.js可以在import的时候直接将路径写到文件夹级就可以了,系统会根据index.js来进行索引导入。
View界面的绑定和事件发送
import reducers from 'your path of reducers'
import { createStore } from 'redux'
let store = createStore(reducers) // 为了避免重复,可以选择在其他地方创建好然后import进来
...
let unsubscribe = store.subscribe(() => {
let newState = store.getState() // 获取更新后最新的state树
component.setState(...) // 这里的component可以是this
})
...
这就完成了对store订阅的一个功能。一般而言,在setState的时候,没必要把整棵state树放进去,只需要根据我们创建state树的结构取出需要被监听修改的状态即可。
至于事件的发送,在你触发操作的方法里使用store.dispatch(...)
就够了。需要填入参数就是你的Action,这个Action没什么特别的,其本质就是一个包含有type和其他参数的对象。Redux是建议我们给每个Action写ActionCreator来实现,将type固化到每一个actionCreator方法中。
- 写一个ActionCreator例子 (这部分一般都被独立出来定义,建议写到对应的Reducer中,这样逻辑关系泾渭分明)
plusOne(a, b, c) {
return {
type: 'PLUS_ONE',
payload: {
a, b, c
}
}
}
type一般以常量的形式给出。这样,在导入了对应的ActionCreator方法之后,就可以通过store.dispatch(plusOne('poberWong', 'male', '1993'))
的形式来派发这个Action了。
在项目中接入使用React-Redux
上述的用法让人觉得稍微有些死板,这里react-redux带你装逼带你飞
以下是React项目中index.js中的核心代码:import React from 'react'
import { render } from 'react-dom'
import App from './containers/App'
import todoApp from './reducers'
render(
<App/>
, document.getElementById('root'))
- 接入的方式如下:
- 从redux中导入createStore方法,这个用来将写好的reducer包装为store
- 从react-redux 中导入Provider组件,用来包裹我们应用的根组件
。其原理是利用组件的Context属性来实现对store的全局分发。
经过处理的index.js 如下:import React from 'react'
import { render } from 'react-dom'
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import App from './containers/App'
import todoApp from './reducers'
let store = createStore(todoApp)
render(
<Provider store={store}>
<App/>
</Provider>
, document.getElementById('root'))
在View中花式玩转Redux
- 先呈上一个简单的Demo案例
import React from 'react'
import {increase, decrease} from 'it is the path'
import {connect} from 'react-redux'
class App extends React.Component{
render() {
return (
<div>
<button onClick={this._onClick.bind(this)}>{this.props.counter}</button>
</div>)
}
_onClick () {
this.props.dispatch(increase(...))
}
function select (state) { // 手动注入state,dispatch分发器被connect自动注入
return { // 注入的内容自行选择
counter: state.counter
}
}
export default connect(select)(App)
这里的核心在于react-redux中connect的使用。
最后的一个
select
方法是connect方法中的回调函数,负责向当前组件的props中注入state。而在该方法的return方法中,返回的是需要注入的东西。注: 在这里注入之后,就可以在状态树被修改后将值同步过来并重新调用render(), 因此将对应的值应用到与状态相关的模块中于是,如上select部分代码可以写成
export default connect(state => ({counter: state.counter}))(App)
。 如果你需要将整棵状态树同步进来,可以简化为export default connect(state => state)(App)
使用注解进一步简化代码:
(state => state)
export default class extends React.Component{...} // 作为默认导出的模块,类名是可选的分发事件:
this.props.dispatch(increase(2))
实现dispatch与ActionCreator的绑定,进一步优化Redux的使用
以上讲的就是如何通过react-redux
这个库来实现Redux与React的对接。
目前,光这样玩还不够过瘾。当我们实现actionCreator的绑定之后,就可以直接使用creator来派发action了。使用redux提供的bindActionCreator来绑定
import {increase, descrease} from 'it is the path'
const mapDispatchToProps = (dispatch) =>
bindActionCreators({
increase,
decrease
}, dispatch)
@connect(state => state, mapDispatchToProps)
connect参数中的第一个回调方法是用来给当前组件的props注入state状态树的。第二个回调方法,即就是我们在这里用到的对dispatch的绑定。因此,如上代码同样可以用Lambda表达式改写为@connect(state => state, dispatch => bindActionCreators({increase, decrease}, dispatch))
- 此时,被绑定好dispatch的increase和decrease这两个ActionCreator就已经被注入到props中去了。因此我们在我们需要分发action的地方就可以这么写:
this.props.increase(2)
。是不是简单又好用呢?
如果你有解构props或者state的习惯,又会出现如下代码:const {increase, decrease} = this.props
...
increase(2)
...
结语
再次强调一下,本文不适合初学者看,本文旨在于React中提高Redux的使用效率以及理解之间的结构关系。如果想要入门Redux,笔者推荐中文文档的如下章节:
##号外!!!
我司举办的开发大赛,欢迎参加喔~
详情请见官网: https://applean.cn