教你实现一个超级mini-zustand,学不会来打我(持续更新中)

150 阅读1分钟

Zustand采用发布订阅者模式,实现了createStore方法

简易实现

下面实现一个简单的mini_createStore方法,基于发布订阅

const mini_createStore = () => {
	let state;
	const listeners = new Set()
	
	const getState = () => state
	
	const setState = (newState) => {
		state = newState 
		// * 通知订阅者
		listeners.forEach(listener=>linstener())
	}

	// * 创建订阅方法
	const subcribe = (listener) => {
		// * 添加到订阅者列表中
		listeners.add(listener)
		
		// * 返回取消订阅的方法
	    return (listener) => listeners.delete(listener)
	}

	return {
		getState,
		setState,
		subcribe
	}
}

问题思考

这样简单的代码存在以下问题:

初始化问题

我们使用:

const store = mini_createStore()

后,再使用store.getState()查看storestate的值

console.log(store.getState()) // undefined

会发现他是undefined, but why?

因为我们在mini_createStore中这样使用创建了state

let state

但是并没有初始化他,因此我们需要一个初始化方法。

此时我们让mini_createStroe接受一个方法,用于初始化state,如下:

const mini_createStore = (crateInitialState) => {
  let state
  const listeners = new Set()
 

  const getState = () => state
  
  const setState = (newState) => {
    .....  
  }
  
  const subcribe = (listener) => {
    .............
  }
  // * 初始化state
  state = crateInitialState()  
  
  return .....
}

现在我们已经可以正确的得到初始值啦:

const store = mini_createStore(()=>( {count: 0} ))
console.log(store.getState()) // * { count: 0 }

newState方法问题

由于我们这样给state赋值,

state = newState 

有时我们期待使用方法来使用prevState改变state,如下:

store.setState((state) => ({ count: state.count + 1 }))

但是当我们打印store.getState()得到:

console.log(store.getState()) // * [Function (anonymous)]

因此我们需要特判一下传入的newState类型,如下:

state = typeof newState === "Function" ? newState(state) : newState

现在我们已经可以通过方法来改变state

const store = mini_createStore(() => ({ count: 0 }))
store.setState((state) => ({ count: state.count + 1 }))
console.log(store.getState()) // * { count: 1}