Redux源码学习篇(一) -- redux实现

关于redux 源码学习系列文章,是通过阅读 《react 状态管理与同构》后的读书笔记和心得。

本文会逐步探索redux到应用分为3个系列

  1. redux 实现
  2. react-redux 实现
  3. redux中间件的应用与实现

简单入手

案例场景: 现在有一个计数器,+、-(或者点赞场景),现在用redux如何记录呢?

 import {createStore,combineReducers } from 'redux'
 //action
const LIKE = "LIKE";
const UNLIKE = "UNLIKE";
const initialState=0;

const reducer = (state=initialState, action) => {
  switch (action.type) {
    case LIKE:
      return state + 1;
    case UNLIKE:
      return state - 1;
    default:
      return initialState;
  }
};
const store = createStore(combineReducers({ user:reducer }));

console.log("init", store.getState());
const render = () => {
  console.log("render", store.getState());
};
store.subscribe(render);
store.dispatch({ type: LIKE });
// console.log("like", store.getState());
store.dispatch({ type: LIKE });
// console.log("like", store.getState());

redux 实现

redux帮我们解决了跨越多组件通信问题,即提供了一个管理公共状态的方案。

createStore

store 作为一个对象,提供了直接获取页面数据状态的 getState 方法、触发更新 store
dispatch 方法,以及订阅 store 状态变化的 subscribe 方法等,进而维护了整个应用 的数据状态和页面渲染。如下是 store 的重要方法.

canst store= createStore(reducer, preloadedState, enhancer); 

const store={
dispatch,
getState,
subscribe,
replaceReducer
}

store 实现

const createStore=(reducer,initState)=>{
    let state=initState;
    //listeners 用于存储所有监听函数
    let listeners=[];

    const getState=()=>state;

    const dispatch=(action)=>{
        state=reducer(state,action);
        //每次状态更新后,都需要调用listeners数组中的每一个监听函数
        listeners.forEach(listener=>listener())
    }
    const subscribe=(listener)=>{
        //每一次调用时,都将相关的监听函数存入listeners数组中
        listeners.push(listener);
        return ()=>{
            listeners=listeners.filter(item=>item!==listener)
        }
    }
    dispatch({type:'@@redux/INIT'}) //初始化 state
    return{
        getState,
        dispatch,
        subscribe
    }
}

追问环节

  1. 创建的时候为什么需要 dispatch({type:'@@redux/INIT'})

是为了首次初始化store

  1. 是如何监听store变化的?
    通过观察者模式,即 dispatch 起到通知的作用,subscribe即注册监听者(观察者)

观察者模式

下图是具体UML实现图
Redux源码学习篇(一) -- redux实现_第1张图片

// 观察者
class Observer{
    public update:Function
    constructor(fn:Function){
        this.update=fn
    }
}

class Subject{
    private observers:Observer[]
    constructor(){
        //观察者队列
        this.observers=[]
    }
    //添加观察者
    addObserver(observer:Observer){
        this.observers.push(observer)
    }
    //通知所有观察者
    notify(){
        this.observers.forEach(observer=>{
            observer.update()
        })
    }
}

var subject=new Subject();
const say=()=>console.log('call Observer');

const ob1=new Observer(say);
const ob2=new Observer(say);

subject.addObserver(ob1);
subject.addObserver(ob2);

subject.notify()

combineReducers

combineReducers 方法,它实现了接收多个 reducer 函数,并进行整合生成一个rootReducer。

/**
 * 
 * @param {*} reducers  
 * @returns 一个归一化的rootReducer函数,
 * 该函数返回值是经过各个reducers计算后的State
 */
const combineReducers = reducers => {
  return (state = {}, action) => {
    return Object.keys(reducers).reduce((nextState, key) => {
      nextState[key] = reducers[key](state[key], action);
      return nextState;
    }, {});
  };
};

对于用过redux的人来说,它还有一个强大的功能就是可以使用 middlewares(中间件)来完成日志输出、数据分析、错误处理、异步流程等,下一篇将进行中间件中解读。

参考

  1. redux中文官网
  2. 《react 状态管理与同构》书籍

你可能感兴趣的