自己实现一个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;
	/* *********** */
	};
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值