JavaScript系列(41)--状态管理实现详解

devtools/2025/1/24 16:54:48/

JavaScript状态管理实现详解 🔄

今天,让我们深入探讨JavaScript的状态管理实现。状态管理是现代前端应用中的核心概念,它帮助我们有效地管理和同步应用数据。

状态管理基础概念 🌟

💡 小知识:状态管理是一种用于管理应用程序数据流的模式,它通过集中式存储和单向数据流来保持数据的一致性和可预测性。

基本实现 📊

javascript">// 1. 简单的状态存储
class SimpleStore {constructor(initialState = {}) {this.state = initialState;this.listeners = new Set();}getState() {return this.state;}setState(newState) {this.state = { ...this.state, ...newState };this.notify();}subscribe(listener) {this.listeners.add(listener);return () => this.listeners.delete(listener);}notify() {this.listeners.forEach(listener => listener(this.state));}
}// 2. 支持Action的Store
class ActionStore {constructor(reducer, initialState = {}) {this.reducer = reducer;this.state = initialState;this.listeners = new Set();}dispatch(action) {this.state = this.reducer(this.state, action);this.notify();}getState() {return this.state;}subscribe(listener) {this.listeners.add(listener);return () => this.listeners.delete(listener);}notify() {this.listeners.forEach(listener => listener(this.state));}
}// 3. 状态选择器
class StoreSelector {constructor(store) {this.store = store;this.selectors = new Map();this.cache = new Map();store.subscribe(() => this.updateSelectors());}addSelector(key, selectorFn) {this.selectors.set(key, selectorFn);this.updateSelector(key);}select(key) {return this.cache.get(key);}updateSelectors() {this.selectors.forEach((_, key) => this.updateSelector(key));}updateSelector(key) {const selector = this.selectors.get(key);const state = this.store.getState();const newValue = selector(state);if (!this.cache.has(key) || !this.shallowEqual(this.cache.get(key), newValue)) {this.cache.set(key, newValue);}}shallowEqual(obj1, obj2) {if (obj1 === obj2) return true;if (!obj1 || !obj2) return false;return Object.keys(obj1).every(key => obj1[key] === obj2[key]);}
}

高级功能实现 🚀

javascript">// 1. 中间件系统
class MiddlewareStore {constructor(reducer, initialState = {}) {this.reducer = reducer;this.state = initialState;this.listeners = new Set();this.middlewares = [];}use(middleware) {this.middlewares.push(middleware);}dispatch(action) {const middlewareAPI = {getState: () => this.state,dispatch: (action) => this.dispatch(action)};const chain = this.middlewares.map(middleware => middleware(middlewareAPI));const composedDispatch = this.compose(...chain)(this.baseDispatch.bind(this));composedDispatch(action);}baseDispatch(action) {this.state = this.reducer(this.state, action);this.notify();}compose(...funcs) {if (funcs.length === 0) return arg => arg;if (funcs.length === 1) return funcs[0];return funcs.reduce((a, b) => (...args) => a(b(...args)));}// ... 其他基本方法同ActionStore
}// 2. 时间旅行调试器
class TimeTravel {constructor(store) {this.store = store;this.history = [{ state: store.getState(), action: '@@INIT' }];this.currentIndex = 0;store.subscribe(() => {if (this.isTimeTraveling) return;this.history = this.history.slice(0, this.currentIndex + 1);this.history.push({state: store.getState(),action: this.lastAction});this.currentIndex = this.history.length - 1;});}recordAction(action) {this.lastAction = action;}undo() {if (this.currentIndex > 0) {this.isTimeTraveling = true;this.currentIndex--;this.store.setState(this.history[this.currentIndex].state);this.isTimeTraveling = false;}}redo() {if (this.currentIndex < this.history.length - 1) {this.isTimeTraveling = true;this.currentIndex++;this.store.setState(this.history[this.currentIndex].state);this.isTimeTraveling = false;}}getHistory() {return this.history;}jumpTo(index) {if (index >= 0 && index < this.history.length) {this.isTimeTraveling = true;this.currentIndex = index;this.store.setState(this.history[index].state);this.isTimeTraveling = false;}}
}// 3. 状态持久化
class PersistentStore {constructor(store, options = {}) {this.store = store;this.options = {key: 'app_state',storage: localStorage,serialize: JSON.stringify,deserialize: JSON.parse,...options};this.init();}init() {// 加载持久化的状态const savedState = this.options.storage.getItem(this.options.key);if (savedState) {try {const state = this.options.deserialize(savedState);this.store.setState(state);} catch (error) {console.error('Failed to load persisted state:', error);}}// 订阅状态变化this.store.subscribe(() => this.persist());}persist() {try {const state = this.store.getState();const serialized = this.options.serialize(state);this.options.storage.setItem(this.options.key, serialized);} catch (error) {console.error('Failed to persist state:', error);}}clear() {this.options.storage.removeItem(this.options.key);}
}

性能优化技巧 ⚡

javascript">// 1. 批量更新优化
class BatchUpdateStore {constructor(initialState = {}) {this.state = initialState;this.listeners = new Set();this.pendingUpdates = new Map();this.isUpdating = false;}setState(key, value) {this.pendingUpdates.set(key, value);this.scheduleBatchUpdate();}scheduleBatchUpdate() {if (!this.isUpdating) {this.isUpdating = true;Promise.resolve().then(() => this.processBatchUpdate());}}processBatchUpdate() {const newState = { ...this.state };this.pendingUpdates.forEach((value, key) => {newState[key] = value;});this.state = newState;this.pendingUpdates.clear();this.isUpdating = false;this.notify();}
}// 2. 选择器优化
class MemoizedSelector {constructor() {this.cache = new Map();this.lastArgs = new Map();}createSelector(dependencies, combiner) {return (...args) => {const key = JSON.stringify(args);const depValues = dependencies.map(dep => dep(...args));// 检查依赖是否改变if (this.shouldUpdate(key, depValues)) {const result = combiner(...depValues);this.cache.set(key, result);this.lastArgs.set(key, depValues);}return this.cache.get(key);};}shouldUpdate(key, newArgs) {if (!this.cache.has(key)) return true;const lastArgs = this.lastArgs.get(key);return !lastArgs || !this.shallowEqual(lastArgs, newArgs);}shallowEqual(arr1, arr2) {return arr1.length === arr2.length &&arr1.every((item, index) => item === arr2[index]);}
}// 3. 状态分片
class SlicedStore {constructor() {this.slices = new Map();this.listeners = new Map();}createSlice(name, reducer, initialState) {if (this.slices.has(name)) {throw new Error(`Slice ${name} already exists`);}this.slices.set(name, {state: initialState,reducer});this.listeners.set(name, new Set());}dispatch(sliceName, action) {const slice = this.slices.get(sliceName);if (!slice) {throw new Error(`Slice ${sliceName} not found`);}const newState = slice.reducer(slice.state, action);if (newState !== slice.state) {slice.state = newState;this.notifySliceListeners(sliceName);}}subscribe(sliceName, listener) {const listeners = this.listeners.get(sliceName);if (!listeners) {throw new Error(`Slice ${sliceName} not found`);}listeners.add(listener);return () => listeners.delete(listener);}notifySliceListeners(sliceName) {const listeners = this.listeners.get(sliceName);const state = this.slices.get(sliceName).state;listeners.forEach(listener => listener(state));}
}

最佳实践建议 💡

  1. 状态设计模式
javascript">// 1. 状态隔离
class IsolatedStore {constructor() {this.stores = new Map();}createStore(name, initialState) {if (this.stores.has(name)) {throw new Error(`Store ${name} already exists`);}const store = new SimpleStore(initialState);this.stores.set(name, store);return store;}getStore(name) {const store = this.stores.get(name);if (!store) {throw new Error(`Store ${name} not found`);}return store;}
}// 2. 状态同步
class SyncedStore {constructor(stores) {this.stores = stores;this.syncListeners = new Map();}sync(sourceStore, targetStore, mapper) {const unsubscribe = sourceStore.subscribe(state => {const mappedState = mapper(state);targetStore.setState(mappedState);});this.syncListeners.set(`${sourceStore.name}-${targetStore.name}`,unsubscribe);}unsync(sourceStore, targetStore) {const key = `${sourceStore.name}-${targetStore.name}`;const unsubscribe = this.syncListeners.get(key);if (unsubscribe) {unsubscribe();this.syncListeners.delete(key);}}
}// 3. 状态验证
class ValidatedStore {constructor(schema) {this.schema = schema;this.store = new SimpleStore();}setState(newState) {const validationResult = this.validateState(newState);if (validationResult.isValid) {this.store.setState(newState);} else {throw new Error(`Invalid state: ${validationResult.errors.join(', ')}`);}}validateState(state) {const errors = [];let isValid = true;Object.entries(this.schema).forEach(([key, validator]) => {if (!validator(state[key])) {isValid = false;errors.push(`Invalid value for ${key}`);}});return { isValid, errors };}
}

结语 📝

状态管理是现代JavaScript应用中的核心概念,通过本文,我们学习了:

  1. 状态管理的基本概念和实现
  2. 高级功能如中间件和时间旅行
  3. 性能优化技巧
  4. 最佳实践和设计模式
  5. 状态验证和同步策略

💡 学习建议:在实践中,要根据应用的规模和复杂度选择合适的状态管理方案。对于小型应用,简单的状态存储就足够了;对于大型应用,则需要考虑使用更完整的状态管理解决方案。


如果你觉得这篇文章有帮助,欢迎点赞收藏,也期待在评论区看到你的想法和建议!👇

终身学习,共同成长。

咱们下一期见

💻


http://www.ppmy.cn/devtools/153185.html

相关文章

autogen 中的 Teams 示例

目录 1 .Creating a Team2. Running a Team3. Observing a Team4. Resetting a Team5. Stopping a Team6. Resuming a Team7. Aborting a Team8. 额外的例子 1 .Creating a Team import asynciofrom autogen_agentchat.agents import AssistantAgent from autogen_agentchat.b…

kconfig语法里,怎么实现二选一配置?

在Kconfig语法中&#xff0c;可以使用choice和endchoice关键字来实现二选一配置。以下是一个示例&#xff0c;展示了如何在Kconfig文件中实现二选一配置&#xff1a; config EXAMPLEbool "Example configuration"default y if EXAMPLE choiceprompt "Select on…

HTML5使用favicon.ico图标

目录 1. 使用favicon.ico图标 1. 使用favicon.ico图标 favicon.ico一般用于作为网站标志&#xff0c;它显示在浏览器的地址栏或者标签上 制作favicon图标 选择一个png转ico的在线网站&#xff0c;这里以https://www.bitbug.net/为例。上传图片&#xff0c;目标尺寸选择48x48&a…

IP所属地与上网地点:如何匹配?

一&#xff0c;揭秘IP地址及其所属地&#xff1a;网络世界的关键标识与地理位置关系 在互联网的世界中&#xff0c;每个接入网络的设备被赋予了一个独一无二的身份标识&#xff0c;即IP地址&#xff0c;它相当于设备的“数字身份证”。在信息传递和网络通信的过程中&#xff0…

面试题-OpenFeign详解

1、Feign是什么&#xff1f; Feign也是一个狠角色&#xff0c;Feign旨在使得Java Http客户端变得更容易。 Feign集成了Ribbon、RestTemplate实现了负载均衡的执行Http调用&#xff0c;只不过对原有的方式&#xff08;RibbonRestTemplate&#xff09;进行了封装&#xff0c;开…

【2024 - 年终总结】叶子增长,期待花开

写在前面&#xff1a;本博客仅作记录学习之用&#xff0c;部分图片来自网络&#xff0c;如需引用请注明出处&#xff0c;同时如有侵犯您的权益&#xff0c;请联系删除&#xff01; 文章目录 前言论博客创作保持2024的记录清单博客科研开源工作生活 总结与展望互动致谢参考 前言…

GitHub的主要用途及核心功能

------> 在给手机成功root之后&#xff0c;我也经常光临GitHub&#xff0c;在上面挖掘好玩的模块还有&#xff0c;并根据其源代码进行学习。那GitHub是什么网站呢&#xff1f;它又有什么功能&#xff1f; GitHub 是什么&#xff1f; GitHub 是一个基于 Git 的版本控制和代…

《探秘鸿蒙Next:非结构化数据处理与模型轻量化的完美适配》

在鸿蒙Next的人工智能应用场景中&#xff0c;处理非结构化数据并使其适配模型轻量化需求是一项关键且具有挑战性的任务。以下是一些有效的方法和策略。 数据预处理 数据清洗&#xff1a;非结构化数据中往往存在噪声、重复和错误数据。对于文本数据&#xff0c;要去除乱码、特殊…