从源码到实践理解redux

从源码到实践理解redux

  1. 原理
  2. redux源码分析
  3. 购物车案例

本文会先从源码分析如何实现redux,然后通过一个购物车案例来实践。

原理

从源码到实践理解redux_第1张图片
在分析redux源码,先了解一种订阅模式,这对后面的理解是有帮助的,如图所示:
从源码到实践理解redux_第2张图片

redux源码分析

为了更好的理解,这里采用了类来实现(redux源码是函数闭包实现)

class store {
  constructor(combinedReducer, initState){
    this.state = initState;   //状态树
    this.listeners = [];      //订阅表(订阅者列表)
    this.combinedReducer = combinedReducer; //状态改变方法
  }

  // 获取状态树
  getState = ()=>{
    return this.state
  }


  // 发布(触发事件)
  dispatch = (action)=>{
    //修改状态
        //根据action.type找到修改的位置,根据action.payload的值修改原状态的值
    this.state = combinedReducer(this.state,action) 
    //通知订阅者
        //执行每个订阅者的监听函数
    listeners.forEach((fn) => fn()) 
  }

  // 订阅(绑定事件)
  subscribe = (listener)=>{
    this.listeners.push(listener)
  }

}

/**
 * 功能:创建并返回一个store对象
 */
const createStore = (combinedReducer,initState)=>{
  return new store(combinedReducer,initState)
}


/**
 * 功能:组装多个reducer函数,返回一个改变状态的纯函数
 */
combineReducers = (reducers)=>{
  return function(state={},action={}){
    for(let reducer of reducers){
      newState[reducer] = reducer(state[reducer],action)
    }
    return newState
  }
}

// 对外提供两个方法
export {createStore,combineReducers}

购物车案例

carPage : 购物车页面; starPage : 收藏夹页面; productPage : 商品详情页面

功能:加入购物车;收藏商品;

代码:

/*------------------------使用---------------------------------*/

import { combineReducers,createStore } from "./store"

// 1.自定义的reducer
const carPageReducer = (state, action) =>{
  switch(action.type){
    case ADD_TO_CAR:
      return {...state,totalNum:state.totalNum+1}
  }
}

const starPageReducer = (state, action) =>{
  switch(action.type){
    case STAR_PRODUCT:
      const newStars = [...stars,action.payload.productId] 
      return {...state, stars:newStars}
  }
}


// 2.组装reducer,创建store
const initState = {
    //购物车页面的状态
  carPageReducer:{ 
    totalNum:0
  },
    //收藏页面的状态
  starPageReducer:{
    stars:['商品X','商品Y'],
  }
}
const combinedReducer = combineReducers([carPageReducer,starPageReducer])
const store = createStore(combinedReducer,initState)


// 3.订阅
// 在页面carPage中
subscribe(()=>{
  document.querySelector('#totalNum').innerHTML = store.getState().carPageReducer.totalNum;
})
// 在页面starPage中
subscribe(()=>{
  document.querySelector('#stars').innerHTML = createComponent(store.getState().starPageReducer.stars);
})


// 4.发布
// 在productPage页面中
const addToCarAction = {
  type: "ADD_TO_CAR",
  payload: {}
}
store.dispath(addToCarAction)

const starAction = {
  type: "STAR_PRODUCT",
  payload: {productId:'商品Z'}
}
store.dispath(starAction)

流程图:
从源码到实践理解redux_第3张图片

你可能感兴趣的