手把手教你写一个极简React全局状态管理器

前言

大家好这里是阳九,一个中途转行的野路子码农,热衷于研究和手写前端工具.

我的宗旨就是 万物皆可手写

新手创作不易,有问题欢迎指出和轻喷,谢谢

本文章适合有一定React开发经验,并且对redux这类写起来烦的一匹的库深恶痛绝的前端开发

Redux难用?

没错,redux确实难用, 这玩意核心源码只有区区几百行,意味着它偏向底层(但是居然有人为了这几百行代码写一整本书= =)

而如果你是一些小公司,使用redux必将会大大增加开发工作量。

我们的需求就是,来一个新手前端,只需要看三分钟文档就会用!!!

自定义store用法

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实现全局状态管理

我们知道 useState返回了setState方法 那么当组件使用全局状态时,将这个setValue函数保存到数组里,再批量执行,不就实现了全局状态更新?

const [value,setValue] = useState(0) 

自定义store.useState

我们可以在使用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;};
} 

on和off方法

这两个方法用于保存和销毁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);}}} 

自定义store.setState方法

此时我们已经有了使用全局状态组件的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);}} 

更新组件updateComponents

 // 遍历所有需要更新的状态批量执行_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的提问。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

你可能感兴趣的:(react.js,前端,javascript)