mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
small qweb optimisation: reuse bound handlers if possible
This commit is contained in:
@@ -33,6 +33,7 @@ interface Meta<T extends WEnv> {
|
|||||||
renderId: number;
|
renderId: number;
|
||||||
renderProps: any;
|
renderProps: any;
|
||||||
renderPromise: Promise<VNode> | null;
|
renderPromise: Promise<VNode> | null;
|
||||||
|
boundHandlers: { [key: number]: any };
|
||||||
}
|
}
|
||||||
|
|
||||||
const patch = init([sdListeners, sdAttrs]);
|
const patch = init([sdListeners, sdAttrs]);
|
||||||
@@ -100,7 +101,8 @@ export class Component<
|
|||||||
cmap: {},
|
cmap: {},
|
||||||
renderId: 1,
|
renderId: 1,
|
||||||
renderPromise: null,
|
renderPromise: null,
|
||||||
renderProps: props
|
renderProps: props,
|
||||||
|
boundHandlers: {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,7 +253,10 @@ export class Component<
|
|||||||
this.__widget__.renderId++;
|
this.__widget__.renderId++;
|
||||||
const promises: Promise<void>[] = [];
|
const promises: Promise<void>[] = [];
|
||||||
const template = this.inlineTemplate || this.template;
|
const template = this.inlineTemplate || this.template;
|
||||||
let vnode = this.env.qweb.render(template, this, { promises });
|
let vnode = this.env.qweb.render(template, this, {
|
||||||
|
promises,
|
||||||
|
handlers: this.__widget__.boundHandlers
|
||||||
|
});
|
||||||
|
|
||||||
// this part is critical for the patching process to be done correctly. The
|
// this part is critical for the patching process to be done correctly. The
|
||||||
// tricky part is that a child widget can be rerendered on its own, which
|
// tricky part is that a child widget can be rerendered on its own, which
|
||||||
|
|||||||
@@ -722,10 +722,11 @@ const onDirective: Directive = {
|
|||||||
return "";
|
return "";
|
||||||
});
|
});
|
||||||
ctx.addLine(
|
ctx.addLine(
|
||||||
`p${nodeID}.on = {${eventName}: context['${handler}'].bind(owner${
|
`extra.handlers[${nodeID}] = extra.handlers[${nodeID}] || context['${handler}'].bind(owner${
|
||||||
extraArgs ? ", " + qweb._formatExpression(extraArgs) : ""
|
extraArgs ? ", " + qweb._formatExpression(extraArgs) : ""
|
||||||
})};`
|
});`
|
||||||
);
|
);
|
||||||
|
ctx.addLine(`p${nodeID}.on = {${eventName}: extra.handlers[${nodeID}]};`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -890,7 +890,8 @@ exports[`t-on can bind event handler 1`] = `
|
|||||||
let h = this.h;
|
let h = this.h;
|
||||||
let c1 = [], p1 = {};
|
let c1 = [], p1 = {};
|
||||||
let vn1 = h('button', p1, c1);
|
let vn1 = h('button', p1, c1);
|
||||||
p1.on = {click: context['add'].bind(owner)};
|
extra.handlers[1] = extra.handlers[1] || context['add'].bind(owner);
|
||||||
|
p1.on = {click: extra.handlers[1]};
|
||||||
c1.push({text: \`Click\`});
|
c1.push({text: \`Click\`});
|
||||||
return vn1;
|
return vn1;
|
||||||
}"
|
}"
|
||||||
@@ -903,7 +904,8 @@ exports[`t-on can bind handlers with arguments 1`] = `
|
|||||||
let h = this.h;
|
let h = this.h;
|
||||||
let c1 = [], p1 = {};
|
let c1 = [], p1 = {};
|
||||||
let vn1 = h('button', p1, c1);
|
let vn1 = h('button', p1, c1);
|
||||||
p1.on = {click: context['add'].bind(owner, 5)};
|
extra.handlers[1] = extra.handlers[1] || context['add'].bind(owner, 5);
|
||||||
|
p1.on = {click: extra.handlers[1]};
|
||||||
c1.push({text: \`Click\`});
|
c1.push({text: \`Click\`});
|
||||||
return vn1;
|
return vn1;
|
||||||
}"
|
}"
|
||||||
@@ -937,7 +939,8 @@ exports[`t-on can bind handlers with loop variable as argument 1`] = `
|
|||||||
let c6 = [], p6 = {};
|
let c6 = [], p6 = {};
|
||||||
let vn6 = h('a', p6, c6);
|
let vn6 = h('a', p6, c6);
|
||||||
c5.push(vn6);
|
c5.push(vn6);
|
||||||
p6.on = {click: context['activate'].bind(owner, context['action'])};
|
extra.handlers[6] = extra.handlers[6] || context['activate'].bind(owner, context['action']);
|
||||||
|
p6.on = {click: extra.handlers[6]};
|
||||||
c6.push({text: \`link\`});
|
c6.push({text: \`link\`});
|
||||||
}
|
}
|
||||||
c1.push({text: \`
|
c1.push({text: \`
|
||||||
@@ -953,7 +956,8 @@ exports[`t-on handler is bound to proper owner 1`] = `
|
|||||||
let h = this.h;
|
let h = this.h;
|
||||||
let c1 = [], p1 = {};
|
let c1 = [], p1 = {};
|
||||||
let vn1 = h('button', p1, c1);
|
let vn1 = h('button', p1, c1);
|
||||||
p1.on = {click: context['add'].bind(owner)};
|
extra.handlers[1] = extra.handlers[1] || context['add'].bind(owner);
|
||||||
|
p1.on = {click: extra.handlers[1]};
|
||||||
c1.push({text: \`Click\`});
|
c1.push({text: \`Click\`});
|
||||||
return vn1;
|
return vn1;
|
||||||
}"
|
}"
|
||||||
|
|||||||
@@ -25,9 +25,10 @@ function trim(str: string): string {
|
|||||||
function renderToDOM(
|
function renderToDOM(
|
||||||
qweb: QWeb,
|
qweb: QWeb,
|
||||||
template: string,
|
template: string,
|
||||||
context: EvalContext = {}
|
context: EvalContext = {},
|
||||||
|
extra?: any
|
||||||
): HTMLElement | Text {
|
): HTMLElement | Text {
|
||||||
const vnode = qweb.render(template, context);
|
const vnode = qweb.render(template, context, extra);
|
||||||
|
|
||||||
// we snapshot here the compiled code. This is useful to prevent unwanted code
|
// we snapshot here the compiled code. This is useful to prevent unwanted code
|
||||||
// change.
|
// change.
|
||||||
@@ -658,11 +659,16 @@ describe("t-on", () => {
|
|||||||
test("can bind event handler", () => {
|
test("can bind event handler", () => {
|
||||||
qweb.addTemplate("test", `<button t-on-click="add">Click</button>`);
|
qweb.addTemplate("test", `<button t-on-click="add">Click</button>`);
|
||||||
let a = 1;
|
let a = 1;
|
||||||
const node = renderToDOM(qweb, "test", {
|
const node = renderToDOM(
|
||||||
add() {
|
qweb,
|
||||||
a = 3;
|
"test",
|
||||||
}
|
{
|
||||||
});
|
add() {
|
||||||
|
a = 3;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ handlers: [] }
|
||||||
|
);
|
||||||
(<HTMLElement>node).click();
|
(<HTMLElement>node).click();
|
||||||
expect(a).toBe(3);
|
expect(a).toBe(3);
|
||||||
});
|
});
|
||||||
@@ -670,11 +676,16 @@ describe("t-on", () => {
|
|||||||
test("can bind handlers with arguments", () => {
|
test("can bind handlers with arguments", () => {
|
||||||
qweb.addTemplate("test", `<button t-on-click="add(5)">Click</button>`);
|
qweb.addTemplate("test", `<button t-on-click="add(5)">Click</button>`);
|
||||||
let a = 1;
|
let a = 1;
|
||||||
const node = renderToDOM(qweb, "test", {
|
const node = renderToDOM(
|
||||||
add(n) {
|
qweb,
|
||||||
a = a + n;
|
"test",
|
||||||
}
|
{
|
||||||
});
|
add(n) {
|
||||||
|
a = a + n;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ handlers: [] }
|
||||||
|
);
|
||||||
(<HTMLElement>node).click();
|
(<HTMLElement>node).click();
|
||||||
expect(a).toBe(6);
|
expect(a).toBe(6);
|
||||||
});
|
});
|
||||||
@@ -688,11 +699,16 @@ describe("t-on", () => {
|
|||||||
<li t-foreach="['someval']" t-as="action"><a t-on-click="activate(action)">link</a></li>
|
<li t-foreach="['someval']" t-as="action"><a t-on-click="activate(action)">link</a></li>
|
||||||
</ul>`
|
</ul>`
|
||||||
);
|
);
|
||||||
const node = renderToDOM(qweb, "test", {
|
const node = renderToDOM(
|
||||||
activate(action) {
|
qweb,
|
||||||
expect(action).toBe("someval");
|
"test",
|
||||||
}
|
{
|
||||||
});
|
activate(action) {
|
||||||
|
expect(action).toBe("someval");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ handlers: [] }
|
||||||
|
);
|
||||||
(<HTMLElement>node).getElementsByTagName("a")[0].click();
|
(<HTMLElement>node).getElementsByTagName("a")[0].click();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -704,7 +720,7 @@ describe("t-on", () => {
|
|||||||
expect(this).toBe(owner);
|
expect(this).toBe(owner);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const node = renderToDOM(qweb, "test", owner);
|
const node = renderToDOM(qweb, "test", owner, { handlers: [] });
|
||||||
(<HTMLElement>node).click();
|
(<HTMLElement>node).click();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user