大家好这里是阳九,一个中途转行的野路子码农,热衷于研究和手写前端工具.
我的宗旨就是 万物皆可手写
新手创作不易,有问题欢迎指出和轻喷,谢谢
本文章适合有一定React开发经验,并且对redux这类写起来烦的一匹的库深恶痛绝的前端开发
没错,redux确实难用, 这玩意核心源码只有区区几百行,意味着它偏向底层(但是居然有人为了这几百行代码写一整本书= =)
而如果你是一些小公司,使用redux必将会大大增加开发工作量。
我们的需求就是,来一个新手前端,只需要看三分钟文档就会用!!!
import Store from './store'
const store = new Store({age:18,name:'张三'})
function App(){const {age} = store.useState(['age'])const addAge = ()=>{store.setState({age:age+1}) }return ( {age})
}
我们知道 useState返回了setState方法 那么当组件使用全局状态时,将这个setValue函数保存到数组里,再批量执行,不就实现了全局状态更新?
const [value,setValue] = useState(0)
我们可以在使用store.useState时,将React.useState的setValue方法取出并保存起来 保存到store的_event中, 也就是on方法
自定义store.useState方法
class Store{private _events: Record = {}; // 保存所有的updater key为状态名private _state: any = {};// store中保存的state... useState(keys: string[]) {// 使用useState 保存状态const [value, setValue] = useState(this._state);//创建updater const updater = (newVal: any) => {setValue(newVal);};// 将使用的states作为依赖统一注册updater(首屏时即注册)useEffect(() => {keys.forEach((key) => {this.on(key, updater);})// 组件销毁时统一销毁所有的updaterreturn () => {keys.forEach((key) => {this.off(key, updater);})};}, keys);return value;};
}
这两个方法用于保存和销毁updater(组件的setValue)
// 将一个updater保存到_event中 on(key: string, updater: Function): void {const s = this._events[key]if (!s) { // 如果没有updater数组则创建一个数组this._events[key] = [updater];} else if (s.indexOf(updater) < 0) {//添加一个updater到数组中s.push(updater);}}// 从_event[key]中移除updateroff(key: string, updater: Function): void {const s = this._events[key];this._events[key] = [updater]if (s) {const index = s.indexOf(updater);if (index >= 0) {s.splice(index, 1);}}}
此时我们已经有了使用全局状态组件的updater,批量执行即可
setState(newStates: Record): void {const needUpdateKeys: any[] = []; // 需要更新的状态// 遍历对比 检出需要更新的状态 Object.keys(newStates).forEach((key) => {if (this._state[key] !== newStates[key]) {needUpdateKeys.push(key);this._state[key] = newStates[key];}})// 更新使用这些state的组件if (needUpdateKeys.length > 0) {this.updateComponents(needUpdateKeys);}}
// 遍历所有需要更新的状态批量执行_event数组内保存的updater, 更新所有组件updateComponents(keys: string[]) {keys.forEach((key) => {const updaters: any[] = this._events[key];if (Array.isArray(updaters)) {updaters.forEach((updater) => {updater(this._state[key]);})}})}
import { useState, useEffect } from 'react';
export class Store {private _events: Record = {}; // 保存所有的updater key为状态名private _state: any = {};// store中保存的stateconstructor(initStates: Record) {this._state = initStates}// _events中保存所有的updater on(key: string, updater: Function): void {const s = this._events[key]if (!s) { // 如果没有updater数组则创建一个数组this._events[key] = [updater];} else if (s.indexOf(updater) < 0) {//添加一个updater到数组中s.push(updater);}}// 从_event[key]中移除updateroff(key: string, updater: Function): void {const s = this._events[key];this._events[key] = [updater]if (s) {const index = s.indexOf(updater);if (index >= 0) {s.splice(index, 1);}}}setState(newStates: Record): void {const needUpdateKeys: any[] = []; // 需要更新的状态// 遍历对比 检出需要更新的状态 Object.keys(newStates).forEach((key) => {if (this._state[key] !== newStates[key]) {needUpdateKeys.push(key);this._state[key] = newStates[key];}})// 更新使用这些state的组件if (needUpdateKeys.length > 0) {this.updateComponents(needUpdateKeys);}}useState(keys: string[]) {// 使用useState 保存状态const [value, setValue] = useState(this._state);//创建updater const updater = () => {setValue(this._state);};// 将使用的states作为依赖统一注册updater(首屏时即注册)useEffect(() => {keys.forEach((key) => {this.on(key, updater);})// 组件销毁时统一销毁所有的updaterreturn () => {keys.forEach((key) => {this.off(key, updater);})};}, keys);return value;};// 遍历所有需要更新的状态批量执行_event数组内保存的updater, 更新所有组件updateComponents(keys: string[]) {keys.forEach((key) => {const updaters: any[] = this._events[key];if (Array.isArray(updaters)) {updaters.forEach((updater) => {updater(this._state[key]);})}})}
}
当然这里只是提供一个思路,来自己封装全局状态管理器,本次的核心思想就是:保存所有组件的setState函数,统一执行. 当然也可以根据项目添加各种功能,比如函数式修改state,副作用单独处理和拦截器等等。
这里是一个我写的另一个使用观察者模式实现的全局状态管理器,是另一种思路,大家可以参考,核心结构参考了react-Query库
github.com/lzy19926/lz…
整理了75个JS高频面试题,并给出了答案和解析,基本上可以保证你能应付面试官关于JS的提问。
有需要的小伙伴,可以点击下方卡片领取,无偿分享