change subscribe

This commit is contained in:
Sergey Krylov 2022-06-30 10:25:57 +05:00
parent a860f8d093
commit f0d90741dd
6 changed files with 67 additions and 11 deletions

View File

@ -2,6 +2,7 @@ import { Store } from '../../core/createStore';
import { $, Dom } from '../../core/dom'; import { $, Dom } from '../../core/dom';
import { Emitter } from '../../core/Emitter'; import { Emitter } from '../../core/Emitter';
import { ExcelComponent } from '../../core/ExcelComponent'; import { ExcelComponent } from '../../core/ExcelComponent';
import { StoreSubscriber } from '../../core/StoreSubscriber';
interface ExcelOptionsType { interface ExcelOptionsType {
components: any[], components: any[],
@ -13,12 +14,14 @@ export class Excel {
components: any[]; components: any[];
emitter: Emitter; emitter: Emitter;
store: Store; store: Store;
subscriber: StoreSubscriber;
constructor(selector: string, options: ExcelOptionsType) { constructor(selector: string, options: ExcelOptionsType) {
this.$el = $(selector); this.$el = $(selector);
this.components = options.components; this.components = options.components;
this.emitter = new Emitter(); this.emitter = new Emitter();
this.store = options.store; this.store = options.store;
this.subscriber = new StoreSubscriber(this.store);
console.log(`Created new Excel class in ${selector} with options: ${options}`); console.log(`Created new Excel class in ${selector} with options: ${options}`);
} }
@ -46,10 +49,13 @@ export class Excel {
render() { render() {
this.$el.append(this.getRoot()); this.$el.append(this.getRoot());
this.subscriber.subscribeComponents(this.components);
this.components.forEach(component => component.init()); this.components.forEach(component => component.init());
} }
destroy() { destroy() {
this.subscriber.unsubscribeFromStore();
this.components.forEach(component => component.destroy()); this.components.forEach(component => component.destroy());
} }
} }

View File

@ -10,6 +10,7 @@ export class Formula extends ExcelComponent {
super($root, { super($root, {
listeners: ['input', 'keydown'], listeners: ['input', 'keydown'],
name: 'Formula', name: 'Formula',
subscribe: ['currentText'],
...options, ...options,
}); });
} }
@ -26,16 +27,13 @@ export class Formula extends ExcelComponent {
this.formulaInput = this.$root.find('#formula-input'); this.formulaInput = this.$root.find('#formula-input');
// this.$on('table:input', text => {
// this.formulaInput.text = text;
// });
this.$on('table:select-cell', text => { this.$on('table:select-cell', text => {
this.formulaInput.text = text; this.formulaInput.text = text;
}); });
}
this.$subscribe(state => { storeChanged({ currentText = '' }) {
this.formulaInput.text = state.currentText; this.formulaInput.text = currentText;
});
} }
onInput(event: Event) { onInput(event: Event) {

View File

@ -1,4 +1,4 @@
import { ActionType, StateType, SubscribeType } from '../redux/types'; import { ActionType, SubscribeType } from '../redux/types';
import { Store } from './createStore'; import { Store } from './createStore';
import { DomListener } from './DomListener'; import { DomListener } from './DomListener';
import { Emitter } from './Emitter'; import { Emitter } from './Emitter';
@ -6,6 +6,7 @@ import { Emitter } from './Emitter';
interface ExcelComponentClass { interface ExcelComponentClass {
toHTML: () => string; toHTML: () => string;
prepare: () => void; prepare: () => void;
storeChanged?: (args: any) => void;
} }
type OptionsType = { type OptionsType = {
@ -13,13 +14,15 @@ type OptionsType = {
name: string; name: string;
emitter?: Emitter; emitter?: Emitter;
store: Store; store: Store;
subscribe: string[],
}; };
export class ExcelComponent extends DomListener implements ExcelComponentClass { export abstract class ExcelComponent extends DomListener implements ExcelComponentClass {
name: string; name: string;
emitter: Emitter; emitter: Emitter;
store: Store; store: Store;
storeSub: SubscribeType; storeSub: SubscribeType;
subscribe: string[];
private unsubscribers: ((args?: any) => any)[]; private unsubscribers: ((args?: any) => any)[];
constructor($root: any, options: OptionsType) { constructor($root: any, options: OptionsType) {
@ -27,6 +30,8 @@ export class ExcelComponent extends DomListener implements ExcelComponentClass {
this.name = options?.name; this.name = options?.name;
this.emitter = options?.emitter; this.emitter = options?.emitter;
this.store = options?.store; this.store = options?.store;
this.subscribe = options?.subscribe;
this.unsubscribers = []; this.unsubscribers = [];
this.prepare(); this.prepare();
} }
@ -52,8 +57,12 @@ export class ExcelComponent extends DomListener implements ExcelComponentClass {
this.store.dispatch(action); this.store.dispatch(action);
} }
$subscribe(fn: (state?: StateType) => void) { storeChanged(args?: any) {
this.storeSub = this.store.subscribe(fn); console.log('CHANGE STORE: ', args);
}
isWatching(key: string) {
return this.subscribe?.includes(key);
} }
init() { init() {

View File

@ -0,0 +1,35 @@
import { StateType } from '../redux/types';
import { Store } from './createStore';
import { isEqual } from './utils';
export class StoreSubscriber {
sub: any;
prevState: StateType;
constructor(private store: Store) {
this.sub = null;
this.prevState = {};
}
subscribeComponents(components: any[]) {
this.prevState = this.store.getState();
this.sub = this.store.subscribe((state: StateType) => {
Object.keys(state).forEach(key => {
if (!isEqual(this.prevState[key], state[key])) {
components.forEach(component => {
if (component.isWatching(key)) {
const changes = { [key]: state[key] };
component.storeChanged(changes);
}
});
}
});
this.prevState = this.store.getState();
});
}
unsubscribeFromStore() {
this.sub.unsubscribe();
}
}

View File

@ -37,6 +37,6 @@ export class Store {
} }
getState() { getState() {
return this.state; return JSON.parse(JSON.stringify(this.state));
} }
} }

View File

@ -11,3 +11,11 @@ export function storage(key: string, data: any = null): any {
return true; return true;
} }
export function isEqual(a: any, b: any) {
if (typeof a === 'object' && typeof b === 'object') {
return JSON.stringify(a) === JSON.stringify(b);
}
return a === b;
}