UNPKG

@idooel/runtime-context

Version:

Runtime data pool with namespaces, stackable contexts, subscriptions and optional persistence. Vue adapter included.

118 lines (102 loc) 3.19 kB
import Vue from 'vue' import { createDataPool, DataPool } from '../core/DataPool' import type { Namespace, DataKey, Subscriber, DataEvent } from '../core/types' declare module 'vue/types/vue' { interface Vue { $idooelDataPool: DataPool } } export interface Vue2DataPoolOptions { pool?: DataPool globalInject?: boolean mixin?: boolean } const Vue2DataPoolPlugin = { install(Vue: any, options: Vue2DataPoolOptions = {}) { const pool = options.pool || createDataPool() // 全局注入 if (options.globalInject !== false) { Vue.prototype.$idooelDataPool = pool Vue.$idooelDataPool = pool } // 全局混入 if (options.mixin !== false) { Vue.mixin({ created() { // 为每个组件创建数据池引用 this._idooelDataPoolSubscriptions = [] }, beforeDestroy() { // 清理订阅 if (this._idooelDataPoolSubscriptions) { this._idooelDataPoolSubscriptions.forEach((unsub: any) => { try { unsub() } catch { // 忽略取消订阅时的错误 } }) this._idooelDataPoolSubscriptions = [] } } }) } } } export function useDataPool(): DataPool { if (!Vue.prototype.$idooelDataPool) { throw new Error('Vue2DataPool plugin not installed. Please install it with Vue.use(Vue2DataPoolPlugin)') } return Vue.prototype.$idooelDataPool } export function usePoolValue<T = unknown>( ns: Namespace, key: DataKey, fallback?: T ) { const pool = useDataPool() // 创建响应式数据 const value = Vue.observable({ data: pool.get(ns, key, fallback) }) // 获取当前组件实例 const vm = Vue.prototype._isVue ? Vue.prototype : getCurrentVueInstance() if (vm && vm._idooelDataPoolSubscriptions) { // 订阅数据变更 const unsubscribe = pool.subscribe<T>({ ns, key }, (event: DataEvent<T>) => { value.data = event.value }) vm._idooelDataPoolSubscriptions.push(unsubscribe) } return { value: value.data, set: (newValue: T) => pool.set(ns, key, newValue), delete: () => pool.delete(ns, key) } } export function usePoolSubscription<T = unknown>( filter: { ns?: Namespace; key?: DataKey }, callback: Subscriber<T> ) { const pool = useDataPool() const vm = getCurrentVueInstance() if (vm && vm._idooelDataPoolSubscriptions) { const unsubscribe = pool.subscribe<T>(filter, callback) vm._idooelDataPoolSubscriptions.push(unsubscribe) return unsubscribe } return pool.subscribe<T>(filter, callback) } // 辅助函数:获取当前 Vue 实例 function getCurrentVueInstance(): any { // 在 Vue 2 中,通过全局混入的 created 钩子可以访问当前实例 // 这里需要通过其他方式获取实例,实际使用中可以通过函数调用上下文获取 try { // 尝试获取当前组件实例(这需要在特定上下文中调用) return Vue.prototype._isVue ? Vue.prototype : null } catch { return null } } export { Vue2DataPoolPlugin, createDataPool } export default Vue2DataPoolPlugin