From 65c1ea893003fad35b878677c9cb578472195f2c Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 12 Nov 2018 22:07:55 -0500 Subject: [PATCH] wip: defer patchData as nodeOp --- packages/runtime-core/src/createRenderer.ts | 61 ++++++++++++++------- packages/scheduler/src/index.ts | 10 +++- 2 files changed, 49 insertions(+), 22 deletions(-) diff --git a/packages/runtime-core/src/createRenderer.ts b/packages/runtime-core/src/createRenderer.ts index 9b9021ce9b..82492381a9 100644 --- a/packages/runtime-core/src/createRenderer.ts +++ b/packages/runtime-core/src/createRenderer.ts @@ -105,7 +105,7 @@ export function createRenderer(options: RendererOptions) { teardownVNode } = options - function insertOrAppend( + function queueInsertOrAppend( container: RenderNode, newNode: RenderNode, refNode: RenderNode | null @@ -161,10 +161,23 @@ export function createRenderer(options: RendererOptions) { ) { const { flags, tag, data, children, childFlags, ref } = vnode isSVG = isSVG || (flags & VNodeFlags.ELEMENT_SVG) > 0 + // element creation is not deferred since it doesn't produce + // user-affecting side effects until inserted into the DOM const el = (vnode.el = platformCreateElement(tag as string, isSVG)) if (data != null) { for (const key in data) { - patchData(el, key, null, data[key], null, vnode, isSVG) + if (!reservedPropRE.test(key)) { + platformPatchData( + el, + key, + null, + data[key], + null, + vnode, + isSVG, + unmountChildren + ) + } } if (data.vnodeBeforeMount) { data.vnodeBeforeMount(vnode) @@ -185,7 +198,7 @@ export function createRenderer(options: RendererOptions) { } } if (container != null) { - insertOrAppend(container, el, endNode) + queueInsertOrAppend(container, el, endNode) } if (ref) { queueEffect(() => { @@ -330,7 +343,7 @@ export function createRenderer(options: RendererOptions) { ) { const el = (vnode.el = platformCreateText(vnode.children as string)) if (container != null) { - insertOrAppend(container, el, endNode) + queueInsertOrAppend(container, el, endNode) } } @@ -403,7 +416,7 @@ export function createRenderer(options: RendererOptions) { // patching ------------------------------------------------------------------ - function patchData( + function queuePatchData( el: RenderNode | (() => RenderNode), key: string, prevValue: any, @@ -412,19 +425,19 @@ export function createRenderer(options: RendererOptions) { nextVNode: VNode, isSVG: boolean ) { - if (reservedPropRE.test(key)) { - return + if (!reservedPropRE.test(key)) { + queueNodeOp([ + platformPatchData, + el, + key, + prevValue, + nextValue, + preVNode, + nextVNode, + isSVG, + unmountChildren + ]) } - platformPatchData( - typeof el === 'function' ? el() : el, - key, - prevValue, - nextValue, - preVNode, - nextVNode, - isSVG, - unmountChildren - ) } function patch( @@ -489,7 +502,7 @@ export function createRenderer(options: RendererOptions) { const prevValue = prevDataOrEmpty[key] const nextValue = nextDataOrEmpty[key] if (prevValue !== nextValue) { - patchData( + queuePatchData( el, key, prevValue, @@ -505,7 +518,15 @@ export function createRenderer(options: RendererOptions) { for (const key in prevDataOrEmpty) { const prevValue = prevDataOrEmpty[key] if (prevValue != null && !nextDataOrEmpty.hasOwnProperty(key)) { - patchData(el, key, prevValue, null, prevVNode, nextVNode, isSVG) + queuePatchData( + el, + key, + prevValue, + null, + prevVNode, + nextVNode, + isSVG + ) } } } @@ -1092,7 +1113,7 @@ export function createRenderer(options: RendererOptions) { } } } else { - insertOrAppend(container, vnode.el as RenderNode, refNode) + queueInsertOrAppend(container, vnode.el as RenderNode, refNode) } } diff --git a/packages/scheduler/src/index.ts b/packages/scheduler/src/index.ts index 73ae5a8832..79e9a56491 100644 --- a/packages/scheduler/src/index.ts +++ b/packages/scheduler/src/index.ts @@ -2,7 +2,7 @@ // A data structure that stores a deferred DOM operation. // the first element is the function to call, and the rest of the array -// stores up to 3 arguments. +// stores up to 8 arguments. type Op = [Function, ...any[]] // A "job" stands for a unit of work that needs to be performed. @@ -375,5 +375,11 @@ function commitJob(job: Job) { function applyOp(op: Op) { const fn = op[0] - fn(op[1], op[2], op[3]) + // optimize for more common cases + // only patchData needs 8 arguments + if (op.length <= 3) { + fn(op[1], op[2], op[3]) + } else { + fn(op[1], op[2], op[3], op[4], op[5], op[6], op[7], op[8]) + } } -- 2.47.3