Created
May 26, 2020 02:51
-
-
Save neatorobito/5c0748641cfa7e60aa4698deb4a62c95 to your computer and use it in GitHub Desktop.
State Management for Vue based on almy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import _Vue from 'vue'; | |
export namespace StateService | |
{ | |
export const StorePlugin = { | |
install(Vue : typeof _Vue, options : { stateModel : any }) | |
{ | |
let store = new Store(); | |
if(!options || !options.stateModel) | |
{ | |
throw('Please pass an initial state to the store.'); | |
} | |
store._internal= _Vue.observable(options.stateModel); | |
Vue.prototype.$store = store; | |
} | |
}; | |
export class Store { | |
public _internal : { [key : string] : any } = null; | |
private _listeners : { [key : string] : Array<(value : any) => void> } = null; | |
constructor() | |
{ | |
this.initialize(); | |
} | |
/** | |
* Initializes the state store. | |
* @returns None | |
*/ | |
initialize(): void | |
{ | |
this._internal = {}; | |
this._listeners = {}; | |
} | |
/** | |
* Creates or updates the value in the state store and dispatches notifications to any subscribed handlers. | |
* Listeners are always notified before the value has been updated because they will receive the new value via callback. | |
* @param key - The name of the value | |
* @param value - The value | |
* | |
*/ | |
dispatch(key : string, value : any, doNotOptimize? : boolean, doNotChainDispatch? : boolean): void | |
{ | |
if (this._internal[key] === value && !doNotOptimize) | |
{ | |
return; | |
} | |
if (this._listeners[key]) | |
{ | |
for (let i = 0; i < this._listeners[key].length; ++i) | |
{ | |
this._listeners[key][i](value); | |
} | |
} | |
this._internal[key] = value; | |
if (typeof value === 'object' && !doNotChainDispatch) | |
{ | |
for (let prop in value) { | |
// eslint-disable-next-line no-prototype-builtins | |
if (value.hasOwnProperty(prop)) { | |
this.dispatch(key + '->' + prop, value[prop], doNotOptimize, true); | |
} | |
} | |
} | |
if (/->/.test(key) && !doNotChainDispatch) | |
{ | |
let parentAndChild = key.split('->'); | |
let parent = parentAndChild[0]; | |
let child = parentAndChild[1]; | |
if (!this._internal[parent]) | |
{ | |
this._internal[parent] = {}; | |
} | |
this._internal[parent][child] = value; | |
this.dispatch(parent, this._internal[parent], true, true); | |
} | |
} | |
/** | |
* Retrieves a value from the state store. | |
* | |
* @param key - The name of the value | |
* @returns The value | |
* | |
*/ | |
state<T>(key : string): T | |
{ | |
let foundObj = null; | |
if(key && Object.keys(this._internal).includes(key)) | |
{ | |
foundObj = this._internal[key]; | |
} | |
else | |
{ | |
throw('The item ' + key + ' could not be found in the state store.'); | |
} | |
return foundObj; | |
} | |
/** | |
* Subscribes to dispatched events. | |
* | |
* @param key - The name of the value | |
* @param callback - A function that is called when the value is updated | |
* | |
* @note If a event has been dispatched before, the callback will be called immediately after subscribing. | |
*/ | |
subscribe(key : string, callback : (value : any) => void): void | |
{ | |
if (!this._listeners[key]) | |
{ | |
this._listeners[key] = []; | |
} | |
this._listeners[key].push(callback); | |
if (this._internal[key]) | |
{ | |
callback(this._internal[key]); | |
} | |
} | |
} | |
} | |
declare module 'vue/types/vue' { | |
interface Vue { | |
$store: StateService.Store; | |
} | |
} |
Plugging into Vue in main.ts:
import { StateService } from './services/State.Service';
Vue.use(StateService.StorePlugin, { stateModel : new AppStateModel() });
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Sample model