前端状态管理框架XRedux是依据前端状态管理框架redux仿写的,目前只实现了主要的API,后续会添加其他API的实现。
XRedux仓库地址如下:
gitee仓库
github仓库
一、redux主要API
createStore:根据reducer插件store上下文
getState:获取状态数据
subscribe:监听依赖
dispatch:分发action,触发状态数据更新,从而触发依赖更新
二、XRedux代码实现
1、依葫芦画瓢,先实现大概函数结构
const createStore = (reducer) => {
if(typeof reducer !== 'function') {
throw new Error('reducer must be an function.')
}
const getState = () => {
}
const subscribe = (listener) => {
}
const dispatch = (action) => {
}
return {
getState,
subscribe,
dispatch,
}
}
export {
createStore
}
2、先实现getState函数
const createStore = (reducer) => {
if(typeof reducer !== 'function') {
throw new Error('reducer must be an function.')
}
let state
const getState = () => {
return state
}
return {
getState,
subscribe,
dispatch,
}
}
export {
createStore
}
3、实现subscribe
const createStore = (reducer) => {
if(typeof reducer !== 'function') {
throw new Error('reducer must be an function.')
}
let state
let listeners = []
const getState = () => {
return state
}
const subscribe = (listener) => {
if(typeof listener !== 'function') {
throw new Error('listener must be an function')
}
if(!listeners.includes(listener)) {
listeners.push(listener)
}
return () => {
let index = listeners.indexOf(listener)
listeners.splice(index, 1)
}
}
return {
getState,
subscribe,
dispatch,
}
}
export {
createStore
}
4、实现dispatch
const createStore = (reducer) => {
if(typeof reducer !== 'function') {
throw new Error('reducer must be an function.')
}
let state
let listeners = []
const getState = () => {
return state
}
const subscribe = (listener) => {
if(typeof listener !== 'function') {
throw new Error('listener must be an function')
}
if(!listeners.includes(listener)) {
listeners.push(listener)
}
return () => {
let index = listeners.indexOf(listener)
listeners.splice(index, 1)
}
}
const dispatch = (action) => {
if(!isPlainObject(action)) {
throw new Error('action must be plain object.')
}
if(typeof action.type === 'undefined') {
throw new Error("action must have the property 'type'")
}
state = reducer(state, action)
listeners.forEach(listener => {
listener()
})
return action
}
return {
getState,
subscribe,
dispatch,
}
}
export {
createStore
}
5、初始化默认的store数据
需找一个与业务逻辑冲突很小的一个随机字符串,所以这里采用了redux项目原来的随机字符串规则。
const isPlainObject = (data) => {
return Object.prototype.toString.call(data) === '[object Object]'
}
const createStore = (reducer) => {
if(typeof reducer !== 'function') {
throw new Error('reducer must be an function.')
}
let state
let listeners = []
const getState = () => {
return state
}
const subscribe = (listener) => {
if(typeof listener !== 'function') {
throw new Error('listener must be an function')
}
if(!listeners.includes(listener)) {
listeners.push(listener)
}
return () => {
let index = listeners.indexOf(listener)
listeners.splice(index, 1)
}
}
const dispatch = (action) => {
if(!isPlainObject(action)) {
throw new Error('action must be plain object.')
}
if(typeof action.type === 'undefined') {
throw new Error("action must have the property 'type'")
}
state = reducer(state, action)
listeners.forEach(listener => {
listener()
})
return action
}
const randomStr = () => Math.random().toString(36).substring(7).split('').join('.')
dispatch({
type: '@@XRedux/INIT' + randomStr()
})
return {
getState,
subscribe,
dispatch,
}
}
export {
createStore
}
上面也是完整代码逻辑。