1、Store
即是保存数据的地方,通过createStore
函数生成Store
import { createStore } from 'redux';
const store = createStore(fn);
2、State
就是状态,是数据的集合,可以通过store.getState()
拿到
const state = store.getState();
3、Action
是一个对象,是View
发出的通知,通知State
该发生变化了,其中type
属性是必须的
const action = {
type: 'ADD_TODO',
payload: 'Learn Redux'
};
4、Action Creator
就是可以生成Action
的函数
const ADD_TODO = '添加 TODO';
function addTodo(text) {
return {
type: ADD_TODO,
text
}
}
const action = addTodo('Learn Redux');
5、store.dispatch()
是 View 发出 Action 的唯一方法
store.dispatch(addTodo('Learn Redux'));
6、Reducer 是一个纯函数,它接受 Action 和当前 State 作为参数,返回一个新的 State
const reducer = function (state, action) {
// ...
return new_state;
};
7、store.subscribe
方法可设置监听函数,一旦 State 发生变化,就自动执行这个函数,调用该方法返回的函数,即可解除监听
import { createStore } from 'redux';
const store = createStore(reducer);
store.subscribe(listener);
let unsubscribe = store.subscribe(() =>
console.log(store.getState())
);
unsubscribe();
生成Store的createStore方法可以接受两个参数
let store = createStore(reducer, window.STATE_FROM_SERVER)
Store 提供了三个方法: subscribe, dispatch, getState,其简单实现如下
const createStore = (reducer) => {
let state; // 状态
let listeners = []; // 监听
const getState = () => state;
const dispatch = (action) => {
state = reducer(state, action);
listeners.forEach(listener => listener());
};
const subscribe = (listener) => {
listeners.push(listener);
return () => {
listeners = listeners.filter(l => l !== listener);
}
};
dispatch({});
return { getState, dispatch, subscribe };
};
可以将一个庞大的Reducer根据不同的属性处理,拆分不同的子函数,最终通过combineReducers方法合并
import { combineReducers } from 'redux';
const chatReducer = combineReducers({
chatLog,
statusMessage,
userName
})
可以把所有子 Reducer 放在一个文件里面,然后统一引入
import { combineReducers } from 'redux'
import * as reducers from './reducers'
const reducer = combineReducers(reducers)
首先,用户发出 Action
store.dispatch(action);
然后,Store 自动调用 Reducer,并且传入两个参数:当前 State 和收到的 Action,Reducer 会返回新的 State
let nextState = todoApp(previousState, action);
State 一旦有变化,Store 就会调用监听函数。
// 设置监听函数
store.subscribe(listener);
listener
可以通过store.getState()
得到当前状态。如果使用的是 React,这时可以触发重新渲染 View。
function listerner() {
let newState = store.getState();
component.setState(newState);
}
异步操作就是在 Action 发出以后,过一段时间再执行 Reducer,这需求用到中间件。中间件就是一个函数,可以添加功能,通过applyMiddleware
方法进行使用
import { applyMiddleware, createStore } from 'redux';
import createLogger from 'redux-logger';
const logger = createLogger();
const store = createStore(
reducer,
applyMiddleware(logger)
);
applyMiddlewares
是 Redux 的原生方法,作用是将所有中间件组成一个数组,依次执行。
异步操作的思路可以理解为:
React-Redux 将所有组件分成两大类:UI 组件(presentational component)和容器组件(container component)。
UI 组件有以下几个特征:
this.state
这个变量)this.props
)提供const Title =
value => {value}
;
容器组件的特征:
React-Redux 提供connect
方法,用于从 UI 组件生成容器组件
import { connect } from 'react-redux'
const VisibleTodoList = connect(
mapStateToProps,
mapDispatchToProps
)(TodoList)
TodoList
是 UI 组件,VisibleTodoList
就是由 React-Redux 通过connect
方法自动生成的容器组件,mapStateToProps
负责输入逻辑,即将state
映射到 UI 组件的参数(props
),mapDispatchToProps
负责输出逻辑,即将用户对 UI 组件的操作映射成 Action
connect
方法生成容器组件以后,需要让容器组件拿到state
对象,才能生成 UI 组件的参数,React-Redux 提供Provider
组件,可以让容器组件拿到state
import { Provider } from 'react-redux'
import { createStore } from 'redux'
import todoApp from './reducers'
import App from './components/App'
let store = createStore(todoApp);
render(
,
document.getElementById('root')
)
上面代码中,Provider
在根组件外面包了一层,这样一来,App
的所有子组件就默认都可以拿到state
了
Refs: