在vue项目中,一般说到状态管理,我们会想到pinia,它可以帮助我们管理需要在多个页面、组件间共享的数据,并且根据数据的更新触发相关的渲染更新。但如果是数据变化不会引起页面刷新的全局数据呢?
比如我当前开发的项目中,需要在项目初始化之后获取对应的引擎实例,该实例提供相关
api用于处理页面逻辑,但该实例并不会触发页面的更新,此时就需要一个 非响应式的全局状态管理 --globalState
适用场景:
- 全局配置、缓存、临时数据
- 跨页面/组件的事件通知
- 不需要响应式的数据共享
不适用场景
- 需要数据变化时自动刷新页面的场景【用
Pinia或Vuex】
逻辑梳理:
- 定义一个
globalState类,全局只有一个实例 - 维护一份
state数据,提供set、get、has、delete、clear - 提供事件总线功能,用于在不同组件间“广播消息”:
on【监听事件】、emit【触发事件】、off【移除监听】
具体实现代码:
/stores/globalState.ts
// 全局状态管理(非响应式)
/**
* 跨页面/组件共享数据,但又不需要响应式(不需要自动刷新UI)。
* 存储全局配置、缓存、临时数据等。
* 避免污染 window,比直接用 window.xxx 更安全、可控、易维护。
* 比 Pinia/Vuex 更轻量,适合存储不需要响应式的数据。
*/
class GlobalState {
private static instance: GlobalState
private state: Map<string, any> = new Map()
private eventListeners: Map<string, Function[]> = new Map()
static getInstance(): GlobalState {
if(!GlobalState.instance) {
GlobalState.instance = new GlobalState()
}
return GlobalState.instance
}
set(key: string, value: any): void {
this.state.set(key, value)
}
get(key: string): any {
return this.state.get(key)
}
has(key: string): boolean {
return this.state.has(key)
}
delete(key: string): boolean {
return this.state.delete(key)
}
clear(): void {
this.state.clear()
}
// 新增事件总线功能
on(eventName: string, callback: Function): void {
if(!this.eventListeners.has(eventName)) {
this.eventListeners.set(eventName, [])
}
this.eventListeners.get(eventName)?.push(callback)
}
emit(eventName: string, data?: any): void {
const listeners = this.eventListeners.get(eventName)
if(listeners) {
listeners.forEach(callback => {
try {
callback(data)
} catch (error) {
console.error('事件回调执行错误:', error)
}
})
}
}
off(eventName: string, callback?: Function): void {
if (!callback) {
this.eventListeners.delete(eventName)
} else {
const listeners = this.eventListeners.get(eventName)
if (listeners) {
const index = listeners.indexOf(callback)
if (index > -1) {
listeners.splice(index, 1)
}
}
}
}
}
export const globalState = GlobalState.getInstance()
使用
- 组件A --
a.vue【当引擎实例化成功后,设置引擎数据,并触发广播,在适合的时机销毁相关数据】
// a.vue 当引擎实例化成功后,设置引擎数据,并触发广播
import { globalState } from "@/stores/globalState";
const InstanceHasInited = (data) => {
if (engine) {
globalState.set("engineInstance", data);
// 触发事件,通知其他组件
globalState.emit("engineInstance:created", data);
}
});
// 销毁相关数据
onUnmounted(() => {
globalState.delete("engineInstance");
globalState.off("engineInstance:created");
});
- 组件B --
b.vue【在需要使用引擎api获取数据的位置添加监听】
import { globalState } from "@/stores/globalState";
const handleInstanceCreated = (engine: Engine) => {
if(engine) {
// 调用相关api
}
}
onMounted(() => {
// 监听引擎实例创建事件
globalState.on("engineInstance:created", handleInstanceCreated);
})