react-router-redux 提供了以下几个API
export ConnectedRouter from './ConnectedRouter'
export { getLocation, createMatchSelector } from './selectors'
export { LOCATION_CHANGE, routerReducer } from './reducer'
export {
CALL_HISTORY_METHOD,
push, replace, go, goBack, goForward,
routerActions
} from './actions'
export routerMiddleware from './middleware'
ConnectedRouter 从名字看是连接到Router,把在根Router后面做一层包装,主要的作用是订阅Router的location
的变化,location
变化会派发一个LOCATION_CHANGE
的action
。
订阅 history 即 location
componentDidMount() {
const { history } = this.props
this.unsubscribeFromHistory = history.listen(this.handleLocationChange)
}
location 变化派发一个LOCATION_CHANGE
的action
handleLocationChange = location => {
this.store.dispatch({
type: LOCATION_CHANGE,
payload: location
})
}
componentWillMount() {
const { store:propsStore, history } = this.props
this.store = propsStore || this.context.store
this.handleLocationChange(history.location)
}
获取当前state
中存的location
export const getLocation = state => state.router.location
创建一个匹配选择器。就是根据传入的path
与当前state
中的路径pathname
(注意不是location
)进行匹配,匹配成功返回router
的Macth
结构对象(结构:{props,pathname}
),如果匹配失败返回最后一次匹配成功的Match
一个常量,用作location
改变时派发action
的type
属性值
export const LOCATION_CHANGE = '@@router/LOCATION_CHANGE'
首先从名字上看就知道,它是一个reducer
。他的功能是在Router
改变的时候生成新的state
。
export function routerReducer(state = initialState, { type, payload } = {}) {
if (type === LOCATION_CHANGE) {
return { ...state, location: payload }
}
return state
}
一个常量,调用history
操作是派发action
的type
值。history
操作一般有
push
: 新增一个路径replace
:替换现有的路径,没有堆栈所以不能回退。go
:跳转到指定堆栈位置,是个数字goBack
:回退goForward
: 前进
export const CALL_HISTORY_METHOD = '@@router/CALL_HISTORY_METHOD'
function updateLocation(method) {
return (...args) => ({
type: CALL_HISTORY_METHOD,
payload: { method, args }
})
}
/**
* These actions correspond to the history API.
* The associated routerMiddleware will capture these events before they get to
* your reducer and reissue them as the matching function on your history.
*/
export const push = updateLocation('push')
export const replace = updateLocation('replace')
export const go = updateLocation('go')
export const goBack = updateLocation('goBack')
export const goForward = updateLocation('goForward')
export const routerActions = { push, replace, go, goBack, goForward }
路由中间件。将注入的histroy
和对外提供的操作hisotry
的接口关联。前面我们说到有push
,replace
等很多操作history
的API,都是通过这个中间件来操作history
对象。
import { CALL_HISTORY_METHOD } from './actions'
/**
* This middleware captures CALL_HISTORY_METHOD actions to redirect to the
* provided history object. This will prevent these actions from reaching your
* reducer or any middleware that comes after this one.
*/
export default function routerMiddleware(history) {
return () => next => action => {
if (action.type !== CALL_HISTORY_METHOD) {
return next(action)
}
const { payload: { method, args } } = action
history[method](...args)
}
}
ES6代码理解起来,还是有些吃力。转成ES5代码后:
function routerMiddleware(history) {
return function () {
return function (next) {
return function (action) {
// 不是操纵历史,action继续下发
if (action.type !== CALL_HISTORY_METHOD) {
return next(action);
}
var _action$payload = action.payload,
method = _action$payload.method,
args = _action$payload.args;
history[method].apply(history, _toConsumableArray(args));
};
};
};
}