自己实现一个Redux。

Redux是一个用于状态管理的js框架,是Flux架构的一种实现(如图)。
Flux

Redux核心概念

  • store
    是一个对象,所有状态集中存储的地方,并全局唯一,称为状态树。并包含以下几个操作方法:
    • getState()获取当前的状态树;
    • dispatch(action)分发一个动作,以改变状态树中对应的状态;
    • subscribe(listener)添加一个监听器,以监听状态树的变化,当状态树变化时,会马上执行传入的函数。会返回一个unsubscribe函数,执行该函数可以解绑该监听器。
    • replaceReducer(nextReducer)用于热加载,暂时不重要。
  • reducer
    为一个用户自定义的函数,在store分发(dispacth)action时提供处理方法去更新状态树中的状态。应该为一个纯函数。
  • action
    为一个用户自定义的对象,里面包含一个type属性,标识一个动作类型。

核心概念总结:store是存储所有状态的地方,改变状态的唯一方法就是通过调用store的dispatch方法分发相应的动作,该动作会经过每个用户定义的reducer,reducer通过识别action的type,以及接收原来的状态返回一个新的状态。

redux核心api

  • createStore(reducer, initState)根据用户定义的reducer创建一个store。第二个参数为初始状态,可选;
  • combineReducers(reducers)把用户定义的多个reducer合并为一个。

逐步代码实现(涉及ES6语法):

createStore

1、createStore函数的大概样子:

const createStore = (reducer, initState)=>{
	const state = initState || {};	//初始状态;
	
	return {	//store的核心操作方法;
		getState(){
			return state;
		}
		
		dispatch(action){}
		
		subscribe(){}
	};
}

2、dispatch(action)方法实现:
dispatch方法是比较复杂的一个方法,应做的工作有:检测action,检测及防止dispatch死循环,触发监听器。

const createStore = (reducer, initState)=>{
	let state = initState || {};		//初始状态;
	/*  新增代码  */
	let inDispatch = false;		//是否正在分发action
	const listeners = [];		//监听器
	/* *********** */
	
	return {	//store的核心操作方法;
		getState(){
			return state;
		}
		
		dispatch(action){
		/*  新增代码  */
			//1、检测action合法性
			if(!action || typeof action !== 'object' || !action.type){
				throw new Error('action invalid');
			}
			//2、检测是否正在分发,以防止在reducer中调用dispatch而导致死循环。
			if(inDispatch){
				throw new Error('can not dispatch a action now!');
			}
			//3、分发action
			try{
				inDispatch = true;
				state = reducer(state, action);
			}finally{
				inDispatch = false;
			}
			//4、触发所有监听器
			listeners.forEach(listener => listener());
		/* *********** */
		}
		
		subscribe(){}
	};
}

3、subscribe(listener)方法实现:
subscribe方法除了添加监听器之外,还应检测重复监听,返回一个解绑函数。

const createStore = (reducer, initState)=>{
	let state = initState || {};		//初始状态;
	let inDispatch = false;		//是否正在分发action
	const listeners = [];		//监听器
	
	return {	//store的核心操作方法;
		getState(){
			return state;
		}
		
		dispatch(action){
			//1、检测action合法性
			if(!action || typeof action !== 'object' || !action.type){
				throw new Error('action invalid');
			}
			//2、检测是否正在分发,以防止在reducer中调用dispatch而导致死循环。
			if(inDispatch){
				throw new Error('can not dispatch a action now!');
			}
			//3、分发action
			try{
				inDispatch = true;
				state = reducer(state, action);
			}finally{
				inDispatch = false;
			}
			//4、触发所有监听器
			listeners.forEach(listener => listener());
		}
		
		subscribe(listener){
		/*  新增代码  */
			if(listeners.some(item => item===listener))return;	//检测重复监听
			
			const pos = listeners.push(listener) - 1;			//记录该监听器的位置
			return ()=>{
				//返回函数为删除该位置的监听器
				if(listeners[pos] === listener){
					listeners.splice(pos,1);
				}
			};		
		/* *********** */
		}
	};
}

这样,Redux的核心功能就实现了。

combineReducers

实现combineReducers 应该考虑到多层、多个reducer的情况,并且能自动将action逐层分发至每个子reducer。
1、combineReducers大概的样子:

const combineReducers = (reducers){
	if(!reducers || typeof reducers !== 'object'){
		throw new Error('invalid reducers.');
	}
	return (action)=>{};
}

2、关键代码实现:

const combineReducers = (reducers){
	if(!reducers || typeof reducers !== 'object'){
		throw new Error('invalid reducers.');
	}
	return (state, action)=>{
	/*  新增代码  */
		const newState = {};
		for(key in reducers){
			newState[key] = reducers[key](state[key], action);
		}
		return newState;
	/* *********** */
	};
}

猜你喜欢

转载自blog.csdn.net/weixin_43564237/article/details/84402009
今日推荐