状态管理器这么火,让咱们来作一个简单的redux原理解析吧(vuex相似)

redux状态管理器,实质上就是一个单例模式。咱们来实现一个简单的redux模型,实现以前咱们要先熟悉它的用法。 redux

  • Redux是将整个应用状态存储到到一个地方,称为store里面保存一棵状态树(state tree)
  • 组件能够派发(dispatch)行为(action)给store,而不是直接通知其它组件
  • 其它组件能够经过订阅store中的状态(state)来刷新本身的视图.

下面咱们按照这个思想来想一想怎么作。 咱们来抽象一下,提取出最核心的思想,动用鬼斧神工画个图:数组

用文字来描述一下,一个惟一的仓库里,有一个私有属性state,仓库由门卫大哥进行管理,全部对state的操做都要通过门卫大哥,外面的人无权直接对state进行操做,若是有进行订阅,则在状态改变后收到状态改变事件。好了,咱们按照这个思想来开始code吧函数

第一步:声明一个对象

const state={
	a: 1
}

第二步:将对象包裹起来,使其不可随意访问

function createStore(){
	const state={
		a: 1
	}
}

第三步:暴露出一个方法,使外部能够对状态进行操做

function createStore() {
	 let state={
	    a:1
	  };
	function getState() {
		return state //此处直接将state返回,会使state引用地址暴露,从而被引用对象改变值
	}
	return {
		getState
	}
}
let store = createStore()  // 建立一个仓库
let state = store.getState()  // 获取状态state
console.log(store.getState())  //  输出{ a: 1 }
state.a = 2   //将state a的值设置为2
console.log(state)  //  输出为{ a: 2 }
console.log(store.getState()) // 此时仓库中state的值也改变了,输出为{ a: 2 }

因此咱们将第六行 return state 替换为 return JSON.parse(JSON.stringify(state)) 能够避免这个问题。优化

第四步:除了获取状态咱们还须要操做状态,暴露第二个方法,dispatch,顺便将state的初始化进行一下优化

'use strict'
function createStore() {
  let state;
 function getState() {
   return JSON.parse(JSON.stringify(state))
 }
 function dispatch(action) { // 分发
   state = reducer(state,action) // 接收当前 State 和Action做为参数,返回一个新的 State
 }
 dispatch({ type: '@@INIT' }) // 在建立仓库的时候,初始化state的值
 return {
   getState,
   dispatch
 }
}
let initState = {
  count: 0
}
//处理器,接收二个参数 ,接收老状态和action,返回新状态 
function reducer(state = initState, action) { // 若是state没有值,默认值为initState
   //判断动做的类型
   switch (action.type) {
       case 'ADD_TODO': 
           return { ...state, count: action.number }; //...state解构state全部属性,count: action.number覆盖前面的值
       default:
           return state;
   }
}
let store = createStore()  // 建立一个仓库
let state = store.getState()  // 获取状态state
let action = {
 type: 'ADD_TODO',
 number: 1
};
store.dispatch(action);  // 派发一个action,改变state的状态
console.log(store.getState()) // 输出{ count: 1 }

diapatch中执行咱们定义的reducer处理器函数,增删改查。例子演示了先建立一个仓库,在建立新仓库的时候初始化了state。而后diapatch一个action:ADD_TODO,执行的处理是改变count的值,返回一个新的state对象,最后咱们能够看到输出,原来的state在初始化后变成{ count: 0 },又在ADD_TODO后变成了{ count: 1 }。spa

reducer函数是咱们在使用redux时须要本身定义的处理函数。code

至此,咱们已经实现了建立一个仓库,而且能够自定义一些处理函数对state进行操做。还缺了什么呢?在实际项目中,状态改变后咱们的大部分的组件须要当即获得新的状态,而后根据状态改变做出不一样的处理。也就是说组件对state进行一个监听,一旦state发生改变,立马通知到对应的组件。让咱们来继续实现吧。。。cdn

第五步:增长一个订阅功能subscribe

function createStore() {
  let state;
  let listeners = [];
  
 function getState() {
   return JSON.parse(JSON.stringify(state))
 }
 
 function dispatch(action) { // 分发
   state = reducer(state,action); // 接收当前 State 和Action做为参数,返回一个新的 State
   listeners.forEach(listener => listener()) // 一旦状态改变,触发全部的监听函数,这里须要优化,只有相关状态改变才须要触发
 }
 
 function subscribe(listener){ // 订阅,若是需监听状态变化,将监听函数传过来
    listeners.push(listener); // 保存监听函数到监听数组
    return function () { // 返回取消订阅的函数
      listeners = listeners.filter(item => item != listener); // 过滤监听函数
    }
 }
 
 dispatch({ type: '@@INIT' }); // 在建立仓库的时候,初始化state的值
 
 return {
   getState,
   dispatch,
   subscribe
 }
 
}

/*这里是分割线,上面一部分是仓库定义,下面部分是使用方法*/
let initState = {
  count: 0
}
//处理器,接收二个参数 ,接收老状态和action,返回新状态 
function reducer(state = initState, action) { // 若是state没有值,默认值为initState
   //判断动做的类型
   switch (action.type) {
       case 'ADD_TODO': 
           return { ...state, count: action.number }; //...state解构state全部属性,count: action.number覆盖前面的值
       default:
           return state;
   }
}
let store = createStore()  // 建立一个仓库

let action = { // 定义一个action
 type: 'ADD_TODO',
 number: 1
};

let unADD = store.subscribe(function(){ // 监听状态改变
  console.log('状态改变了,如今的state为:')  // 状态改变了,如今的state为:
  console.log(store.getState()) // { count: 1 }
})

store.dispatch(action);  // 派发一个action,改变state的状态
复制代码

铛铛铛~,咱们的redux基本模型就作好了,有什么不懂的能够提问哟~对象

相关文章
相关标签/搜索