[IMP] component: make template key static

closes #288
This commit is contained in:
Géry Debongnie
2019-09-12 09:48:17 +02:00
parent 9b589af75a
commit 5bf7a5c671
5 changed files with 20 additions and 33 deletions
+14 -21
View File
@@ -70,12 +70,6 @@ interface Internal<T extends Env, Props> {
classObj: { [key: string]: boolean } | null; classObj: { [key: string]: boolean } | null;
} }
// If a component does not define explicitely a template
// key, it needs to find a template with its name (or a parent's). This is
// qweb dependant, so we need a place to store this information indexed by
// qweb instances.
const TEMPLATE_MAP: { [key: number]: { [name: string]: string } } = {};
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Component // Component
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -83,7 +77,8 @@ let nextId = 1;
export class Component<T extends Env, Props extends {}, State extends {}> { export class Component<T extends Env, Props extends {}, State extends {}> {
readonly __owl__: Internal<Env, Props>; readonly __owl__: Internal<Env, Props>;
template?: string; static template?: string | null = null;
static _template?: string | null = null;
/** /**
* The `el` is the root element of the component. Note that it could be null: * The `el` is the root element of the component. Note that it could be null:
@@ -527,30 +522,28 @@ export class Component<T extends Env, Props extends {}, State extends {}> {
return Promise.resolve(h("div")); return Promise.resolve(h("div"));
} }
const qweb = this.env.qweb; const qweb = this.env.qweb;
if (!this.template) { let p = (<any>this).constructor;
let tmap = TEMPLATE_MAP[qweb.id]; // console.warn(p, p.template, p._template, 'template' in p, p.hasOwnProperty('template'))
if (!tmap) { if (!p.hasOwnProperty("_template")) {
tmap = {}; if (p.template) {
TEMPLATE_MAP[qweb.id] = tmap; p._template = p.template;
}
let p = (<any>this).constructor;
let name: string = p.name;
let template = tmap[name];
if (template) {
this.template = template;
} else { } else {
// here, the component and none of its superclasses defines a static `template`
// key. So we fall back on looking for a template matching its name (or
// one of its subclass).
let template: string;
while ((template = p.name) && !(template in qweb.templates) && p !== Component) { while ((template = p.name) && !(template in qweb.templates) && p !== Component) {
p = p.__proto__; p = p.__proto__;
} }
if (p === Component) { if (p === Component) {
throw new Error(`Could not find template for component "${this.constructor.name}"`); throw new Error(`Could not find template for component "${this.constructor.name}"`);
} else { } else {
tmap[name] = template; p._template = template;
this.template = template;
} }
} }
} }
__owl__.render = qweb.render.bind(qweb, this.template); __owl__.render = qweb.render.bind(qweb, p._template);
this.__observeState(); this.__observeState();
return this.__render(false, [], scope, vars); return this.__render(false, [], scope, vars);
+2 -8
View File
@@ -125,8 +125,6 @@ function parseXML(xml: string): Document {
return doc; return doc;
} }
let nextID = 1;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// QWeb rendering engine // QWeb rendering engine
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -147,10 +145,6 @@ export class QWeb extends EventBus {
// dev mode enables better error messages or more costly validations // dev mode enables better error messages or more costly validations
static dev: boolean = false; static dev: boolean = false;
// the id field is useful to be able to hash qweb instances. The current
// use case is that component's templates are qweb dependant, and need to be
// able to map a qweb instance to a template name.
id = nextID++;
// slots contains sub templates defined with t-set inside t-component nodes, and // slots contains sub templates defined with t-set inside t-component nodes, and
// are meant to be used by the t-slot directive. // are meant to be used by the t-slot directive.
@@ -326,8 +320,8 @@ export class QWeb extends EventBus {
_compile(name: string, elem: Element, parentContext?: Context): CompiledTemplate { _compile(name: string, elem: Element, parentContext?: Context): CompiledTemplate {
const isDebug = elem.attributes.hasOwnProperty("t-debug"); const isDebug = elem.attributes.hasOwnProperty("t-debug");
const ctx = new Context(name); const ctx = new Context(name);
if (elem.tagName !== 't') { if (elem.tagName !== "t") {
ctx.shouldDefineResult = false; ctx.shouldDefineResult = false;
} }
if (parentContext) { if (parentContext) {
ctx.templates = Object.create(parentContext.templates); ctx.templates = Object.create(parentContext.templates);
+1 -1
View File
@@ -12,7 +12,7 @@ export const LINK_TEMPLATE = `
type Props = Destination; type Props = Destination;
export class Link<Env extends RouterEnv> extends Component<Env, Props, {}> { export class Link<Env extends RouterEnv> extends Component<Env, Props, {}> {
template = LINK_TEMPLATE_NAME; static template = LINK_TEMPLATE_NAME;
href: string = this.env.router.destToPath(this.props); href: string = this.env.router.destToPath(this.props);
async willUpdateProps(nextProps) { async willUpdateProps(nextProps) {
+1 -1
View File
@@ -9,7 +9,7 @@ export const ROUTE_COMPONENT_TEMPLATE = `
</t>`; </t>`;
export class RouteComponent extends Component<any, {}, {}> { export class RouteComponent extends Component<any, {}, {}> {
template = ROUTE_COMPONENT_TEMPLATE_NAME; static template = ROUTE_COMPONENT_TEMPLATE_NAME;
routes: any[] = []; routes: any[] = [];
constructor(parent, props) { constructor(parent, props) {
super(parent, props); super(parent, props);
+2 -2
View File
@@ -1288,7 +1288,7 @@ describe("composition", () => {
</div>` </div>`
); );
class Parent extends Widget { class Parent extends Widget {
template = "parent"; static template = "parent";
state = { state = {
numbers: [1, 2, 3] numbers: [1, 2, 3]
}; };
@@ -3003,7 +3003,7 @@ describe("can deduce template from name", () => {
test("can find template of parent component, defined by template key", async () => { test("can find template of parent component, defined by template key", async () => {
class ABC extends Widget { class ABC extends Widget {
template = "Achel"; static template = "Achel";
} }
class DEF extends ABC {} class DEF extends ABC {}
env.qweb.addTemplate("Achel", "<span>Orval</span>"); env.qweb.addTemplate("Achel", "<span>Orval</span>");