redux基本概念
基本概念
1.store
用來保存數據的地方,使用createStore來生成數據
store = createStore(fn)
2.state,經過拷貝store中的數據獲得
state = store.getState()
3.action,用來表示視圖發生的變化
action = {
type:'ADD_TODO',
payload:'Learn Redux'
}
4.Action Creator 用來生成action
const ADD_TODO = '添加 TODO'
function addTodo(text){
return {
type:ADD_TODO,
text
}
}
5.dispatch 用來發出action
store.dispatch(addTodo('Learn Redux'));
6.reducer 用來處理action,返回新的state
const reducer = function(state,action){
return new_state
}
createStore
function createStore(reducer,initState,enhancer){
//0.接收state,添加觀察者
let state = initState
let listeners = []
//1. 獲取state
function getState(){
return JSON.parse(JSON.stringify(state))
}
//2.造一個dispatch來發送action
function dispatch(action){
state = reducer(state,action)
listeners.forEach(linstener => linstener())
}
//3.添加訂閱者
function subscribe(listener){
listeners.push(listener)
return function(){
listeners.filter(item => item != listener)
}
}
return {
getState,
dispatch,
subscribe
}
}
combineReducer
//先拿到reducer
function combineReducer(reducer){
//把state和action交給reducer處理
return (state={},action) => (
//拿到對應reducer的處理結果在把原來的屬性拷貝到新對象上
Object.keys(reducer).reduce((cur,key) => {
cur[key] = reducer[key](state[key],action)
return cur
},{})
)
}
bindActionsCreators
function bindActionsCreators(actions,dispatch){
//先拿到actions和dispatch
return Object.keys(actions).reduce((obj,key)=>{
obj[key] = function(){
//等執行的時候在調用真正的actions和dispatch
dispatch(actions[key].apply(null,arguments))
}
return obj
},{})
}
ApplyMiddleware
![image](http://static.javashuo.com/static/loading.gif)
1.在action以後redecer處理以前
中間件的執行過程
![image](http://static.javashuo.com/static/loading.gif)
const middleware (dispatch) => (
(action) => {
console.log('middleware')
dispatch(action)
console.log('after middleware')
}
)
const middleware1 (dispatch) => (
(action) => {
console.log('middleware1')
dispatch(action)
console.log('after middleware1')
}
)
// middleware -> middleware1 -> action -> middleware1 -> middleware
compose函數的虹吸現象
![image](http://static.javashuo.com/static/loading.gif)
//先執行棧頂的middleware而後迴流到棧底的middleware
const compose = (middlewares) => (
middlewares.reduce((a,b) => (
(...args) => a(b(...args))
))
)
中間件的實現
const middleware1 = dispatch => (
action => {
console.log('middleware1')
let res = dispatch(action)
console.log('after middleware1')
return res
}
)
const middleware2 = dispatch => (
action => {
console.log('middleware2')
let res = dispatch(action)
console.log('after middleware2')
return res
}
)
const middleware3 = dispatch => (
action => {
console.log('middleware3')
let res = dispatch(action)
console.log('after middleware3')
return res
}
)
let middlewares = [middleware1,middleware2,middleware3]
const compose = middlewares => middlewares.reduce((a,b) => (
(...args) => a(b(...args))
))
const dispatch = (action) => {
console.log(`action: ${action}`)
return action
}
//這是最後一箇中間件,調用它將返回第一個中間件
const afterDispatch = compose(middlewares)(dispatch)
const testAction = args => ({
type:"ACTION_TEST",
args
})
afterDispatch(testAction('plus!'))
applyMiddleware
const compose = middlewares => middlewares.reduce((a,b) => (
(...args) => a(b(...args))
))
//1.接收中間件
export default function applyMiddleware(...middlewares){
//2.接收store方法
return function(createStore){
//3.接收reducer
return function(reducer){
let store = createStore(reducer)
let dispatch
let middlewareAPI = {
getState:store.getState,
dispatch:action => dispatch(action)
}
//把state和dispatch方法傳給中間件的一個函數
middlewares = middlewares.map(middleware => middleware(middlewareAPI))
//將dispatch傳入中間件,把dispatch傳給最後一箇中間件,把最後一箇中間件的第2個函數傳給上一個函數,虹吸
dispatch = compose(...middlewares)(store.dispatch)
return {
...store,
dispatch //先執行middleware1
}
}
}
}
react-redux
Provider
class Provider extends React.Component{
//靜態屬性childContextTypes聲明提供給子組件的Context對象的屬性,並實現一個實例getChildContext方法,返回一個表明Context的純對象 (plain object) 。
static childContextTypes = {
store:propTypes.object.isRequired
}
getChildContext(){
return {
store:this.props.store
}
}
render(){
return this.props.children
}
}
Connect
function Connect(mapStateToProps,mapDispatchToProps){
return function(WrapedComponent){
class ProxyComponent extends React.Component {
//子組件須要經過一個靜態屬性contextTypes聲明後,才能訪問父組件Context對象的屬性,不然,即便屬性名沒寫錯,拿到的對象也是undefined。
static contextTypes = {
store:propTypes.object
}
constructor(props,context){
super(props,context)
this.store = context.store
//初始化state
this.state = mapStateToProps(
this.store.getState()
)
}
componentWillMount(){
//當state發生變化的時候經過setState更新組件的變化
this.unsubscribe = this.store.subscribe(()=>{
this.setState(mapStateToProps(this.store.getState()));
});
}
componentWillUnmount(){
//當組件刪除的時候取消監聽state的變化
this.unsubscribe();
}
render(){
let actions = {}
if(typeof mapDispatchToProps == 'function'){
actions = mapDispatchToProps(this.store.disaptch);
}else if(typeof mapDispatchToProps == 'object'){
actions = bindActionCreators(mapDispatchToProps,this.store.dispatch);
}
return <WrapedComponent {...this.state} {...actions}/>
}
}
return ProxyComponent
}
}