一、redux 的 API
Redux 的 API 非常少。Redux 定义了一系列的约定(contract)来让你来实现(例如 reducers),同时提供少量辅助函数来把这些约定整合到一起。
这一章会介绍所有的 Redux API。记住,Redux 只关心如何管理 state。在实际的项目中,你还需要使用 UI 绑定库如 react-redux。
顶级暴露的方法
- createStore(reducer, [preloadedState], [enhancer])
- combineReducers(reducers)
- applyMiddleware(...middlewares)
- bindActionCreators(actionCreators, dispatch)
- compose(...functions)
Store API
引入
上面介绍的所有函数都是顶级暴露的方法。都可以这样引入:
ES6
import { createStore } from 'redux';
ES5 (CommonJS)
var createStore = require('redux').createStore;
ES5 (UMD build)
var createStore = Redux.createStore;
二、 react-redux 的 API
React-Redux是在Redux的基础上,将其大量重复的代码进行了封装。
React-Redux 把组件分为两类:UI 组件(Component)和容器组件(Container)
React-Redux 提供 Provider 组件,可以让容器组件拿到 state
【拓展】组件的分类
UI 组件特征:
- 只负责 UI 的呈现,不带有任何业务逻辑
- 没有状态(this.state)
- 所有数据都由组件属性(this.props)提供
- 不使用任何 Redux 的 API
容器组件特征:
- 负责管理数据和业务逻辑,不负责 UI 的呈现
- 带有内部状态
- 通过 Redux 的 API 生成
混合组件(UI + 逻辑):
——一个组件既有 UI 呈现又有业务逻辑
- 外面是一个容器组件,里面包裹一个UI 组件
- 容器组件负责与外部的通信,将数据传给 UI 组件
- UI 组件接受数据,并渲染出视图
1. Provider
Provider其实是一个React 组件,其原理是通过React组件的context 属性实现store 的传递, 进而拿到整个应用的state。
源码解析:
// Provider 实现原理
class Provider extends Component {
getChildContext() {
store: this.props.store
}
render() {
const { children } = this.props
return Children.only(children)
}
}
Provider.childContextTypes = {
store: React.PropTypes.object
}
上面store放在context里,这样页面组件就可以通过context 拿到store
class PageComp extends Component {
render() {
const { store } = this.context;
const state = store.getState();
return (<div>{state.number || ''}</div>)
}
}
PageComp.contextTypes = {
store: React.PropTypes.object
}
利用context对象给所有子组件提供store。不再需要在每个组件都引用store。
import React, { Component } from 'react';
import Context from './context';
// 给connect等方法提供store
export default class Provider extends Component {
render() {
return (
<Context.Provider value={{store: this.props.store}}>
{this.props.children}
</Context.Provider>
)
}
}
2. connect
该方法封装了大量的逻辑,主要如下:
- 给使用connect方法的组件属性自动绑定了dispatch方法;this.props.dispatch
- 给使用connect方法的组件的setState方法自动添加了对仓库的state的订阅
- 给使用connect方法的组件的属性绑定仓库的state值;this.props.XXXX
- 不再使用store.getState方法
- 给使用connect方法的组件的actions自动使用bindActionCreators方法
import React, { Component } from 'react';
import Context from './context';
import { bindActionCreators } from 'redux';
/**
*
* @param {function} mapStateToProps 绑定state到组件的props
* @param {funtion|object} mapDispatchToProps 返回actions对象
*/
export default function(mapStateToProps, mapDispatchToProps) {
return function(WrappedComponent) {
return class extends Component {
static contextType = Context;
constructor(props, context) {
super(props);
// 被映射的state, 即mapStateToProps的返回值, 绑定到组件的props上
this.state = mapStateToProps(context.store.getState());
}
componentDidMount() {
this.unsubscribe = this.context.store.subscribe(() => {
// setState的用法;传一个state对象
this.setState(mapStateToProps(this.context.store.getState()));
})
}
componentWillUnmount() {
this.unsubscribe();
}
render() {
const { dispatch } = this.context.store;
let actions = {};
if (typeof mapDispatchToProps === 'object'){
actions = mapDispatchToProps;
}
if (typeof mapDispatchToProps === 'function') {
actions = mapDispatchToProps(dispatch);
}
const bindActions = bindActionCreators(actions, dispatch)
return (
<WrappedComponent dispatch={dispatch} {...this.state} {...bindActions} />
)
}
}
}
}
本文参考文献:
redux API 官网:https://www.redux.org.cn/docs/api/
阮一峰老师的《Redux 入门教程(三):React-Redux 的用法》:http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_three_react-redux.html
React-Redux常见API:https://www.cnblogs.com/lyraLee/p/12074449.html
redux, react-redux中的重要API解析:https://www.jianshu.com/p/b9e0c931a01a