move internal stuff in _, add unique id for each widget

This commit is contained in:
Géry Debongnie
2019-01-25 14:27:16 +01:00
parent c1dd38bf03
commit 9fc7cf0c68
5 changed files with 60 additions and 21 deletions
+38 -17
View File
@@ -8,17 +8,28 @@ const patch = init([sdListeners, sdAttrs]);
export interface WEnv { export interface WEnv {
qweb: QWeb; qweb: QWeb;
getID(): number;
}
let wl: any[] = [];
(<any>window).wl = wl;
interface Meta<T extends WEnv> {
id: number;
// name: string;
// template: string;
vnode: VNode | null;
isStarted: boolean;
isMounted: boolean;
parent: Widget<T> | null;
children: Widget<T>[];
} }
export class Widget<T extends WEnv> { export class Widget<T extends WEnv> {
_: Meta<WEnv>;
name: string = "widget"; name: string = "widget";
template: string = "<div></div>"; template: string = "<div></div>";
vnode: VNode | null = null;
isStarted: boolean = false;
isMounted: boolean = false;
parent: Widget<T> | null = null;
children: Widget<T>[] = [];
env: T; env: T;
el: HTMLElement | null = null; el: HTMLElement | null = null;
state: Object = {}; state: Object = {};
@@ -29,13 +40,23 @@ export class Widget<T extends WEnv> {
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
constructor(parent: Widget<T> | T, props?: any) { constructor(parent: Widget<T> | T, props?: any) {
wl.push(this);
let p: Widget<T> | null = null;
if (parent instanceof Widget) { if (parent instanceof Widget) {
this.parent = parent; p = parent;
parent.children.push(this); parent._.children.push(this);
this.env = Object.create(parent.env); this.env = Object.create(parent.env);
} else { } else {
this.env = parent; this.env = parent;
} }
this._ = {
id: this.env.getID(),
vnode: null,
isStarted: false,
isMounted: false,
parent: p,
children: []
};
} }
async willStart() {} async willStart() {}
@@ -56,8 +77,8 @@ export class Widget<T extends WEnv> {
if (document.body.contains(target)) { if (document.body.contains(target)) {
this.visitSubTree(w => { this.visitSubTree(w => {
if (!w.isMounted && this.el!.contains(w.el)) { if (!w._.isMounted && this.el!.contains(w.el)) {
w.isMounted = true; w._.isMounted = true;
w.mounted(); w.mounted();
} }
}); });
@@ -78,7 +99,7 @@ export class Widget<T extends WEnv> {
*/ */
async updateState(newState: Object) { async updateState(newState: Object) {
Object.assign(this.state, newState); Object.assign(this.state, newState);
if (this.isStarted) { if (this._.isStarted) {
await this.render(); await this.render();
} }
} }
@@ -92,14 +113,14 @@ export class Widget<T extends WEnv> {
if (!this.el) { if (!this.el) {
this.el = document.createElement(vnode.sel!); this.el = document.createElement(vnode.sel!);
} }
patch(this.vnode || this.el, vnode); patch(this._.vnode || this.el, vnode);
this.vnode = vnode; this._.vnode = vnode;
return vnode; return vnode;
} }
private async _start(): Promise<void> { private async _start(): Promise<void> {
await this.willStart(); await this.willStart();
this.isStarted = true; this._.isStarted = true;
} }
private async _render(): Promise<VNode> { private async _render(): Promise<VNode> {
@@ -114,9 +135,9 @@ export class Widget<T extends WEnv> {
_mount(el: HTMLElement) { _mount(el: HTMLElement) {
this.el = el; this.el = el;
if (this.parent) { if (this._.parent) {
if (this.parent.isMounted) { if (this._.parent._.isMounted) {
this.isMounted = true; this._.isMounted = true;
this.mounted(); this.mounted();
} }
} }
@@ -124,7 +145,7 @@ export class Widget<T extends WEnv> {
private visitSubTree(callback: (w: Widget<T>) => void) { private visitSubTree(callback: (w: Widget<T>) => void) {
callback(this); callback(this);
for (let child of this.children) { for (let child of this._.children) {
child.visitSubTree(callback); child.visitSubTree(callback);
} }
} }
+5
View File
@@ -26,3 +26,8 @@ export function htmlTrim(s: string): string {
} }
return result; return result;
} }
export function idGenerator(): (() => number) {
let nextID = 1;
return () => nextID++;
}
+3 -1
View File
@@ -1,4 +1,5 @@
import { QWeb } from "./core/qweb_vdom"; import { QWeb } from "./core/qweb_vdom";
import { idGenerator } from "./core/utils";
import { WEnv } from "./core/widget"; import { WEnv } from "./core/widget";
import { ActionManager } from "./services/action_manager"; import { ActionManager } from "./services/action_manager";
import { Ajax } from "./services/ajax"; import { Ajax } from "./services/ajax";
@@ -31,6 +32,7 @@ export function makeEnvironment(): Env {
ajax, ajax,
router, router,
actionManager, actionManager,
menus menus,
getID: idGenerator()
}; };
} }
+10 -1
View File
@@ -1,4 +1,4 @@
import { escape, htmlTrim } from "../src/ts/core/utils"; import { escape, htmlTrim, idGenerator } from "../src/ts/core/utils";
describe("escape", () => { describe("escape", () => {
test("normal strings", () => { test("normal strings", () => {
@@ -25,3 +25,12 @@ describe("htmlTrim", () => {
expect(htmlTrim("")).toBe(""); expect(htmlTrim("")).toBe("");
}); });
}); });
describe("idGenerator", () => {
test("basic use", () => {
let gen = idGenerator();
expect(gen()).toBe(1);
expect(gen()).toBe(2);
expect(gen()).toBe(3);
});
});
+4 -2
View File
@@ -1,4 +1,5 @@
import { Widget, WEnv } from "../src/ts/core/widget"; import { Widget, WEnv } from "../src/ts/core/widget";
import { idGenerator } from "../src/ts/core/utils";
import { QWeb } from "../src/ts/core/qweb_vdom"; import { QWeb } from "../src/ts/core/qweb_vdom";
interface Type<T> extends Function { interface Type<T> extends Function {
@@ -9,8 +10,9 @@ type TestEnv = WEnv;
type TestWidget = Widget<TestEnv>; type TestWidget = Widget<TestEnv>;
function makeWidget(W: Type<TestWidget>): TestWidget { function makeWidget(W: Type<TestWidget>): TestWidget {
const env = { const env: WEnv = {
qweb: new QWeb() qweb: new QWeb(),
getID: idGenerator()
}; };
const w = new W(env); const w = new W(env);
return w; return w;