From 31ec3af4d8f5fb77ea5e835019c0ee9ed9ea0c60 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sun, 29 Apr 2018 22:56:39 +0100 Subject: [PATCH] perf(hdom): update event handling in diffAttributes() - avoid replacing element if changed event handlers - update removeAttribs() --- packages/hdom/src/diff.ts | 29 +++++++++++------------------ packages/hdom/src/dom.ts | 11 ++++++++--- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/packages/hdom/src/diff.ts b/packages/hdom/src/diff.ts index 06385f4852..a0b0f96ee9 100644 --- a/packages/hdom/src/diff.ts +++ b/packages/hdom/src/diff.ts @@ -9,8 +9,6 @@ import { setAttrib } from "./dom"; -// import { DEBUG } from "./api"; - const isArray = isa.isArray; const isString = iss.isString; const diffArray = diff.diffArray; @@ -47,7 +45,7 @@ function _diffElement(parent: Element, prev: any, curr: any, child: number) { const edits = delta.linear; const el = parent.children[child]; let i, j, k, eq, e, status, idx, val; - if (edits[0][0] !== 0 || (i = prev[1]).key !== (j = curr[1]).key || hasChangedEvents(i, j)) { + if (edits[0][0] !== 0 || (i = prev[1]).key !== (j = curr[1]).key) { // DEBUG && console.log("replace:", prev, curr); releaseDeep(prev); removeChild(parent, child); @@ -119,30 +117,25 @@ function releaseDeep(tag: any) { (tag).__release.apply(tag, (tag).__args); delete (tag).__release; } - for (let i = tag.length - 1; i >= 2; i--) { + for (let i = tag.length; --i >= 2;) { releaseDeep(tag[i]); } } } -function hasChangedEvents(prev: any, curr: any) { - for (let k in curr) { - if (k.indexOf("on") === 0 && prev[k] !== curr[k]) { - return true; - } - } - return false; -} - function diffAttributes(el: Element, prev: any, curr: any) { let i, e, edits; const delta = diffObject(prev, curr); - removeAttribs(el, delta.dels); - for (edits = delta.edits, i = edits.length - 1; i >= 0; i--) { + removeAttribs(el, delta.dels, prev); + for (edits = delta.edits, i = edits.length; --i >= 0;) { e = edits[i]; - setAttrib(el, e[0], e[1], curr); + const a = e[0]; + if (a.indexOf("on") === 0) { + el.removeEventListener(a.substr(2), prev[a]); + } + setAttrib(el, a, e[1], curr); } - for (edits = delta.adds, i = edits.length - 1; i >= 0; i--) { + for (edits = delta.adds, i = edits.length; --i >= 0;) { e = edits[i]; setAttrib(el, e, curr[e], curr); } @@ -151,7 +144,7 @@ function diffAttributes(el: Element, prev: any, curr: any) { function extractEquivElements(edits: diff.DiffLogEntry[]) { let k, v, e, ek; const equiv = {}; - for (let i = edits.length - 1; i >= 0; i--) { + for (let i = edits.length; --i >= 0;) { e = edits[i]; v = e[2]; if (isArray(v) && (k = v[1].key) !== undefined) { diff --git a/packages/hdom/src/dom.ts b/packages/hdom/src/dom.ts index d36f142dd3..3ccc7ef464 100644 --- a/packages/hdom/src/dom.ts +++ b/packages/hdom/src/dom.ts @@ -161,9 +161,14 @@ export function updateValueAttrib(el: HTMLInputElement, v: any) { } } -export function removeAttribs(el: Element, attribs: string[]) { - for (let i = attribs.length - 1; i >= 0; i--) { - el.removeAttribute(attribs[i]); +export function removeAttribs(el: Element, attribs: string[], prev: any) { + for (let i = attribs.length; --i >= 0;) { + const a = attribs[i]; + if (a.indexOf("on") === 0) { + el.removeEventListener(a.substr(2), prev[a]); + } else { + el.removeAttribute(a); + } } }