0
点赞
收藏
分享

微信扫一扫

React - 28 redux部分源码解析

myRedux.js

import _ from './assets/utils';

/* 实现redux的部分源码 */
export const createStore = function createStore(reducer) {
    if (typeof reducer !== 'function') throw new Error("Expected the root reducer to be a function");

    let state, //存放公共状态
        listeners = []; //事件池

    /* 获取公共状态 */
    const getState = function getState() {
        // 返回公共状态信息即可
        return state;
    };

    /* 向事件池中加入让组件更新的方法 */
    const subscribe = function subscribe(listener) {
        // 规则校验
        if (typeof listener !== "function") throw new TypeError("Expected the listener to be a function");
        // 把传入的方法(让组件更新的办法)加入到事件池中「需要做去重处理」
        if (!listeners.includes(listener)) {
            listeners.push(listener);
        }
        // 返回一个从事件池中移除方法的函数
        return function unsubscribe() {
            let index = listeners.indexOf(listener);
            listeners.splice(index, 1);
        };
    };

    /* 派发任务通知REDUCER执行 */
    const dispatch = function dispatch(action) {
        // 规则校验
        if (!_.isPlainObject(action)) throw new TypeError("Actions must be plain objects");
        if (typeof action.type === "undefined") throw new TypeError("Actions may not have an undefined 'type' property");

        // 把reducer执行,传递:公共状态、行为对象;接收执行的返回值,替换公共状态;
        state = reducer(state, action);

        // 当状态更改,我们还需要把事件池中的方法执行
        listeners.forEach(listener => {
            listener();
        });

        return action;
    };

    /* redux内部会默认进行一次dispatch派发,目的:给公共容器中的状态赋值初始值 */
    const randomString = () => Math.random().toString(36).substring(7).split('').join('.');
    dispatch({
        // type: Symbol()
        type: "@@redux/INIT" + randomString()
    });

    // 返回创建的STORE对象
    return {
        getState,
        subscribe,
        dispatch
    };
};

src/store/index.js

import { createStore } from '../myredux';

/* 管理员:修改STORE容器中的公共状态 */
let initial = {
    supNum: 10,
    oppNum: 5
};
const reducer = function reducer(state = initial, action) {
    // state:存储STORE容器中的公共状态「最开始没有的时候,赋值初始状态值initial」
    // action:每一次基于dispatch派发的时候,传递进来的行为对象「要求必须具备type属性,存储派发的行为标识」
    // 为了接下来的操作中,我们操作state,不会直接修改容器中的状态「要等到最后return的时候」,我们需要先克隆
    state = { ...state };
    // 接下来我们需要基于派发的行为标识,修改STORE容器中的公共状态信息
    switch (action.type) {
        case 'VOTE_SUP':
            state.supNum++;
            break;
        case 'VOTE_OPP':
            state.oppNum++;
            break;
        default:
    }
    // return的内容,会整体替换STORE容器中的状态信息
    return state;
};

/* 创建STORE公共容器 */
const store = createStore(reducer);
export default store;

举报

相关推荐

0 条评论