大型项目中往往会有一份独立于业务的数据管理模块,这个数据可用于整个项目, 也可以在项目中分模块使用,接下来我们手写一份数据管理工具。
首先我们需要使用数据, 并改变数据:
import { broadcast, subscribe } from './utils'
function createStore (initData, reducer) {
// 传入的初始化的数据 Object类型
const state = initData
const useStore = () => {
// 收集依赖
......
return state
}
const dispatch = () => {
// 更新数据
......
// 通知渲染组件
......
}
return { useStore, dispatch }
}
创建store的作用只有两个, 返回我们所需要的数据(useStore),更新数据(dispatch)
import { broadcast, subscribe, unSubscribe } from './utils'
function createStore (initData, reducer) { // 传入的初始化的数据 Object类型
const state = initData
// 模块名
const nameSpace = state.nameSpace const useStore = (nameSpace = nameSpace) => {
// setState的作用是触发渲染
const [, setState] = useState()
// 收集依赖
useEffect(() => {
subscribe(nameSpace, setState)
return () => unSubscribe(nameSpace, setState)
}, [nameSpace])
return state
}
const dispatch = (data) => {
// 比较数据
const isDiff = compareData(data, state)
if (isDiff) {
// 更新数据
updateData()
// 通知渲染组件也是就是render
broadcast()
}
}
return { useStore, dispatch }
}
对比数据:
function compareData (data, state) {
// 把所有值转换成基础类型的值, 因为其中有可能是函数
transFormData(data)
// 比较值是否存在不同
diffData
}
dispatch({
name: 'Claire',
age: () => { return '30' }
})
因为要兼容上面两种使用方法, 需要转换一下,把函数执行一下取出其中的值
function transformData (data) {
const tempPromises = []
const tempObj = {}
if (Object.keys(data).every((key) => {
const isFunc = Object.prototype.toString().call(data[key]) === '[Object Function]' if (ifFunc) tempPromises.push(tempObj[key] = Promise.resolve(data[key]()))
return !isFunc
})) {
return data
} else {
await Promise.all(tempPromises).then(res => {
Object.keys(tempObj).forEach((key, index) => {
data[key] = res[index]
})
})
return data
}
}
对比
const diffData = (oldVal, val) => { if (valueType(oldVal) !== valueType(val)) return true if (val && typeof val === 'object') { try { return JSON.stringify(oldVal) !== JSON.stringify(val) } catch (e) { return true } } return !Object.is(oldVal, val)}
更新数据:
function updateData () {
return {...state, ...data}
}