应用场景
- React 数据是单向传递(一个方向)的,传统的是父子组件直接通信,数据跨组件(兄弟组件间)传递就比较麻烦
设计思想
- 整个应用的状态存储到一个地方:store
- store 里面存储一个状态树 state tree
- 组件dispatch行为action给store(不是直接通过组件)
- 其它组件可以通过订阅store的状态获取新的状态值来刷新自己组件的视图

Redux三大原则
- 整个系统有且仅有一个状态树(包含整个应用的state),存储在store
- state 是只读的,只能通过派发action来改变,reducer来处理action改变state tree
- 单一数据源,统一管理
源码实现
原理分析
redux有一个中间仓库,我们首先去订阅(subscibe)也就是监听状态的改变,我们在状态改变时去通知(dispatch)那些监听函数执行去获取新的状态(getState)
- 我们是通过createStore (这里应用到闭包)创建仓库 store,createStore 有两个入参:一个是 reducer(处理action来改变state tree)一个是加载前的状态
let store = createStore(reducer, preloadedState)
- createStore返回的仓库store 是一个对象,对象有属性:dispatch,getState,subscribe
function createStore(reducer, preloadedState){
let currentState = preloadedState
function getState(){}
function dispatch(){}
function subscribe(){}
return {
dispatch,
getState,
subscribe
}
}
- 订阅:我们在subscribe中将监听函数保存到一个监听函数数组中,并返回一个函数(从监听函数数组中移除该监听),方便后续取消监听
let currentLiseners = []
function subscribe(listener){
currentLiseners.push(listener)
return function unsubscribe(){
let index = currentLisener.indexof(listener)
currentLiseners.splice(index,1)
}
}
- 发布:我们将在dispatch执行reducer方法得到新的状态值,保存在currentState中,然后遍历监听数组,我们状态改变,通知所有监听函数去改变状态
function dispatch(action){
currentState = reducer(currentState,action)
currentLiseners.forEach(listener=>listener())
}
- 获取新的状态值 getState
function getState(){
return currentState
}
代码实现
function createStore(reducer, preloadedState) {
if (typeof reducer != 'function') {
throw new Error('reducer必须是一个函数')
}
let currentState = preloadedState //当前状态
let currentListeners = [] //定义一数组保存当前的监听函数
// 返回当前状态值
function getState() {
return currentState
}
// 派发
function dispatch(action) {
// 动作必须是纯对象
if (
typeof action != 'object' ||
action === null ||
Object.getPrototypeOf(action) !== Object.prototype
) {
throw new Error(
'动作必须是一个纯对象,如果想进行异步操作请使用中间件'
)
}
if (typeof action.type === 'undefined') {
throw new Error(`动作type属性的属性值不能为undefined`)
}
currentState = reducer(currentState, action)
currentListeners.forEach((listener) => listener())
return action
}
// 订阅
function subscribe(listener) {
currentListeners.push(listener)
return function unsubscribe() {
// 取消订阅
const index = currentListeners.indexOf(listener)
currentListeners.splice(index, 1)
}
}
// 默认第一次加载state
dispatch({ type: '@@redux/INIT' })
return {
getState,
dispatch,
subscribe
}
}
export default createStore