mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
move internal stuff in _, add unique id for each widget
This commit is contained in:
@@ -8,17 +8,28 @@ const patch = init([sdListeners, sdAttrs]);
|
||||
|
||||
export interface WEnv {
|
||||
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> {
|
||||
_: Meta<WEnv>;
|
||||
name: string = "widget";
|
||||
template: string = "<div></div>";
|
||||
vnode: VNode | null = null;
|
||||
|
||||
isStarted: boolean = false;
|
||||
isMounted: boolean = false;
|
||||
parent: Widget<T> | null = null;
|
||||
children: Widget<T>[] = [];
|
||||
env: T;
|
||||
el: HTMLElement | null = null;
|
||||
state: Object = {};
|
||||
@@ -29,13 +40,23 @@ export class Widget<T extends WEnv> {
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
constructor(parent: Widget<T> | T, props?: any) {
|
||||
wl.push(this);
|
||||
let p: Widget<T> | null = null;
|
||||
if (parent instanceof Widget) {
|
||||
this.parent = parent;
|
||||
parent.children.push(this);
|
||||
p = parent;
|
||||
parent._.children.push(this);
|
||||
this.env = Object.create(parent.env);
|
||||
} else {
|
||||
this.env = parent;
|
||||
}
|
||||
this._ = {
|
||||
id: this.env.getID(),
|
||||
vnode: null,
|
||||
isStarted: false,
|
||||
isMounted: false,
|
||||
parent: p,
|
||||
children: []
|
||||
};
|
||||
}
|
||||
|
||||
async willStart() {}
|
||||
@@ -56,8 +77,8 @@ export class Widget<T extends WEnv> {
|
||||
|
||||
if (document.body.contains(target)) {
|
||||
this.visitSubTree(w => {
|
||||
if (!w.isMounted && this.el!.contains(w.el)) {
|
||||
w.isMounted = true;
|
||||
if (!w._.isMounted && this.el!.contains(w.el)) {
|
||||
w._.isMounted = true;
|
||||
w.mounted();
|
||||
}
|
||||
});
|
||||
@@ -78,7 +99,7 @@ export class Widget<T extends WEnv> {
|
||||
*/
|
||||
async updateState(newState: Object) {
|
||||
Object.assign(this.state, newState);
|
||||
if (this.isStarted) {
|
||||
if (this._.isStarted) {
|
||||
await this.render();
|
||||
}
|
||||
}
|
||||
@@ -92,14 +113,14 @@ export class Widget<T extends WEnv> {
|
||||
if (!this.el) {
|
||||
this.el = document.createElement(vnode.sel!);
|
||||
}
|
||||
patch(this.vnode || this.el, vnode);
|
||||
this.vnode = vnode;
|
||||
patch(this._.vnode || this.el, vnode);
|
||||
this._.vnode = vnode;
|
||||
return vnode;
|
||||
}
|
||||
|
||||
private async _start(): Promise<void> {
|
||||
await this.willStart();
|
||||
this.isStarted = true;
|
||||
this._.isStarted = true;
|
||||
}
|
||||
|
||||
private async _render(): Promise<VNode> {
|
||||
@@ -114,9 +135,9 @@ export class Widget<T extends WEnv> {
|
||||
|
||||
_mount(el: HTMLElement) {
|
||||
this.el = el;
|
||||
if (this.parent) {
|
||||
if (this.parent.isMounted) {
|
||||
this.isMounted = true;
|
||||
if (this._.parent) {
|
||||
if (this._.parent._.isMounted) {
|
||||
this._.isMounted = true;
|
||||
this.mounted();
|
||||
}
|
||||
}
|
||||
@@ -124,7 +145,7 @@ export class Widget<T extends WEnv> {
|
||||
|
||||
private visitSubTree(callback: (w: Widget<T>) => void) {
|
||||
callback(this);
|
||||
for (let child of this.children) {
|
||||
for (let child of this._.children) {
|
||||
child.visitSubTree(callback);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,3 +26,8 @@ export function htmlTrim(s: string): string {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function idGenerator(): (() => number) {
|
||||
let nextID = 1;
|
||||
return () => nextID++;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { QWeb } from "./core/qweb_vdom";
|
||||
import { idGenerator } from "./core/utils";
|
||||
import { WEnv } from "./core/widget";
|
||||
import { ActionManager } from "./services/action_manager";
|
||||
import { Ajax } from "./services/ajax";
|
||||
@@ -31,6 +32,7 @@ export function makeEnvironment(): Env {
|
||||
ajax,
|
||||
router,
|
||||
actionManager,
|
||||
menus
|
||||
menus,
|
||||
getID: idGenerator()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { escape, htmlTrim } from "../src/ts/core/utils";
|
||||
import { escape, htmlTrim, idGenerator } from "../src/ts/core/utils";
|
||||
|
||||
describe("escape", () => {
|
||||
test("normal strings", () => {
|
||||
@@ -25,3 +25,12 @@ describe("htmlTrim", () => {
|
||||
expect(htmlTrim("")).toBe("");
|
||||
});
|
||||
});
|
||||
|
||||
describe("idGenerator", () => {
|
||||
test("basic use", () => {
|
||||
let gen = idGenerator();
|
||||
expect(gen()).toBe(1);
|
||||
expect(gen()).toBe(2);
|
||||
expect(gen()).toBe(3);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Widget, WEnv } from "../src/ts/core/widget";
|
||||
import { idGenerator } from "../src/ts/core/utils";
|
||||
import { QWeb } from "../src/ts/core/qweb_vdom";
|
||||
|
||||
interface Type<T> extends Function {
|
||||
@@ -9,8 +10,9 @@ type TestEnv = WEnv;
|
||||
type TestWidget = Widget<TestEnv>;
|
||||
|
||||
function makeWidget(W: Type<TestWidget>): TestWidget {
|
||||
const env = {
|
||||
qweb: new QWeb()
|
||||
const env: WEnv = {
|
||||
qweb: new QWeb(),
|
||||
getID: idGenerator()
|
||||
};
|
||||
const w = new W(env);
|
||||
return w;
|
||||
|
||||
Reference in New Issue
Block a user