[REF] add static App.registerTemplate and update Portal to use it

The goal is to get closer to the possibility of using Owl without the
compiler. This commit removes Portal dependency on the compiler, and
opens the way to register pre-compiled template functions.
This commit is contained in:
Géry Debongnie
2022-05-26 22:42:25 +02:00
committed by Sam Degueldre
parent 2b4d8874c7
commit b10a700381
6 changed files with 44 additions and 25 deletions
+29 -5
View File
@@ -1,9 +1,8 @@
import { createBlock, html, list, multi, text, toggler, comment } from "../blockdom";
import { compile, Template } from "../compiler";
import { Portal } from "../portal";
import { compile, Template, TemplateFunction } from "../compiler";
import { Portal, portalTemplate } from "../portal";
import { component, getCurrent } from "../component/component_node";
import { helpers } from "./template_helpers";
import { globalTemplates } from "../utils";
const bdom = { text, createBlock, list, multi, html, toggler, component, comment };
@@ -45,6 +44,9 @@ export interface TemplateSetConfig {
}
export class TemplateSet {
static registerTemplate(name: string, fn: TemplateFunction) {
globalTemplates[name] = fn;
}
dev: boolean;
rawTemplates: typeof globalTemplates = Object.create(globalTemplates);
templates: { [name: string]: Template } = {};
@@ -64,7 +66,12 @@ export class TemplateSet {
addTemplate(name: string, template: string | Element) {
if (name in this.rawTemplates) {
const rawTemplate = this.rawTemplates[name];
const currentAsString = typeof rawTemplate === "string" ? rawTemplate : rawTemplate.outerHTML;
const currentAsString =
typeof rawTemplate === "string"
? rawTemplate
: rawTemplate instanceof Element
? rawTemplate.outerHTML
: rawTemplate.toString();
const newAsString = typeof template === "string" ? template : template.outerHTML;
if (currentAsString === newAsString) {
return;
@@ -97,7 +104,8 @@ export class TemplateSet {
} catch {}
throw new Error(`Missing template: "${name}"${extraInfo}`);
}
const templateFn = this._compileTemplate(name, rawTemplate);
const isFn = typeof rawTemplate === "function" && !(rawTemplate instanceof Element);
const templateFn = isFn ? rawTemplate : this._compileTemplate(name, rawTemplate);
// first add a function to lazily get the template, in case there is a
// recursive call to the template name
const templates = this.templates;
@@ -124,3 +132,19 @@ export class TemplateSet {
return toggler(subTemplate, template.call(owner, ctx, parent, key));
}
}
// -----------------------------------------------------------------------------
// xml tag helper
// -----------------------------------------------------------------------------
export const globalTemplates: { [key: string]: string | Element | TemplateFunction } = {};
export function xml(...args: Parameters<typeof String.raw>) {
const name = `__template__${xml.nextId++}`;
const value = String.raw(...args);
globalTemplates[name] = value;
return name;
}
xml.nextId = 1;
TemplateSet.registerTemplate("__portal__", portalTemplate);
+1 -1
View File
@@ -188,7 +188,7 @@ export class ComponentNode<P extends Props = any, E = any> implements VNode<Comp
props[key] = useState(prop);
}
}
this.component = new C(props, env, this) as any;
this.component = new C(props, env, this);
this.renderFn = app.getTemplate(C.template).bind(this.component, this.component, this);
this.component.setup();
currentNode = null;
+2 -1
View File
@@ -34,12 +34,13 @@ export const blockDom = {
};
export { App, mount } from "./app/app";
export { xml } from "./app/template_set";
export { Component } from "./component/component";
export { useComponent, useState } from "./component/component_node";
export { status } from "./component/status";
export { reactive, markRaw, toRaw } from "./reactivity";
export { useEffect, useEnv, useExternalListener, useRef, useChildSubEnv, useSubEnv } from "./hooks";
export { EventBus, whenReady, loadFile, markup, xml } from "./utils";
export { EventBus, whenReady, loadFile, markup } from "./utils";
export {
onWillStart,
onMounted,
+11 -2
View File
@@ -1,5 +1,5 @@
import { onWillUnmount } from "./component/lifecycle_hooks";
import { xml } from "./utils";
// import { xml } from "./app/template_set";
import { BDom, text, VNode } from "./blockdom";
import { Component } from "./component/component";
@@ -53,8 +53,17 @@ class VPortal extends VText implements Partial<VNode<VPortal>> {
}
}
/**
* <t t-slot="default"/>
*/
export function portalTemplate(app: any, bdom: any, helpers: any) {
let { callSlot } = helpers;
return function template(ctx: any, node: any, key = "") {
return callSlot(ctx, node, key, "default", false, null);
};
}
export class Portal extends Component {
static template = xml`<t t-slot="default"/>`;
static template = "__portal__";
static props = {
target: {
type: String,
-14
View File
@@ -73,17 +73,3 @@ export class Markup extends String {}
export function markup(value: any) {
return new Markup(value);
}
// -----------------------------------------------------------------------------
// xml tag helper
// -----------------------------------------------------------------------------
export const globalTemplates: { [key: string]: string | Element } = {};
export function xml(...args: Parameters<typeof String.raw>) {
const name = `__template__${xml.nextId++}`;
const value = String.raw(...args);
globalTemplates[name] = value;
return name;
}
xml.nextId = 1;
+1 -2
View File
@@ -16,10 +16,9 @@ import {
xml,
} from "../src";
import { helpers } from "../src/app/template_helpers";
import { TemplateSet } from "../src/app/template_set";
import { TemplateSet, globalTemplates } from "../src/app/template_set";
import { BDom } from "../src/blockdom";
import { compile } from "../src/compiler";
import { globalTemplates } from "../src/utils";
const mount = blockDom.mount;