wip: defer patchData as nodeOp

This commit is contained in:
Evan You 2018-11-12 22:07:55 -05:00
parent 2f3ddf20b5
commit 65c1ea8930
2 changed files with 49 additions and 22 deletions

View File

@ -105,7 +105,7 @@ export function createRenderer(options: RendererOptions) {
teardownVNode teardownVNode
} = options } = options
function insertOrAppend( function queueInsertOrAppend(
container: RenderNode, container: RenderNode,
newNode: RenderNode, newNode: RenderNode,
refNode: RenderNode | null refNode: RenderNode | null
@ -161,10 +161,23 @@ export function createRenderer(options: RendererOptions) {
) { ) {
const { flags, tag, data, children, childFlags, ref } = vnode const { flags, tag, data, children, childFlags, ref } = vnode
isSVG = isSVG || (flags & VNodeFlags.ELEMENT_SVG) > 0 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)) const el = (vnode.el = platformCreateElement(tag as string, isSVG))
if (data != null) { if (data != null) {
for (const key in data) { 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) { if (data.vnodeBeforeMount) {
data.vnodeBeforeMount(vnode) data.vnodeBeforeMount(vnode)
@ -185,7 +198,7 @@ export function createRenderer(options: RendererOptions) {
} }
} }
if (container != null) { if (container != null) {
insertOrAppend(container, el, endNode) queueInsertOrAppend(container, el, endNode)
} }
if (ref) { if (ref) {
queueEffect(() => { queueEffect(() => {
@ -330,7 +343,7 @@ export function createRenderer(options: RendererOptions) {
) { ) {
const el = (vnode.el = platformCreateText(vnode.children as string)) const el = (vnode.el = platformCreateText(vnode.children as string))
if (container != null) { if (container != null) {
insertOrAppend(container, el, endNode) queueInsertOrAppend(container, el, endNode)
} }
} }
@ -403,7 +416,7 @@ export function createRenderer(options: RendererOptions) {
// patching ------------------------------------------------------------------ // patching ------------------------------------------------------------------
function patchData( function queuePatchData(
el: RenderNode | (() => RenderNode), el: RenderNode | (() => RenderNode),
key: string, key: string,
prevValue: any, prevValue: any,
@ -412,11 +425,10 @@ export function createRenderer(options: RendererOptions) {
nextVNode: VNode, nextVNode: VNode,
isSVG: boolean isSVG: boolean
) { ) {
if (reservedPropRE.test(key)) { if (!reservedPropRE.test(key)) {
return queueNodeOp([
} platformPatchData,
platformPatchData( el,
typeof el === 'function' ? el() : el,
key, key,
prevValue, prevValue,
nextValue, nextValue,
@ -424,7 +436,8 @@ export function createRenderer(options: RendererOptions) {
nextVNode, nextVNode,
isSVG, isSVG,
unmountChildren unmountChildren
) ])
}
} }
function patch( function patch(
@ -489,7 +502,7 @@ export function createRenderer(options: RendererOptions) {
const prevValue = prevDataOrEmpty[key] const prevValue = prevDataOrEmpty[key]
const nextValue = nextDataOrEmpty[key] const nextValue = nextDataOrEmpty[key]
if (prevValue !== nextValue) { if (prevValue !== nextValue) {
patchData( queuePatchData(
el, el,
key, key,
prevValue, prevValue,
@ -505,7 +518,15 @@ export function createRenderer(options: RendererOptions) {
for (const key in prevDataOrEmpty) { for (const key in prevDataOrEmpty) {
const prevValue = prevDataOrEmpty[key] const prevValue = prevDataOrEmpty[key]
if (prevValue != null && !nextDataOrEmpty.hasOwnProperty(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 { } else {
insertOrAppend(container, vnode.el as RenderNode, refNode) queueInsertOrAppend(container, vnode.el as RenderNode, refNode)
} }
} }

View File

@ -2,7 +2,7 @@
// A data structure that stores a deferred DOM operation. // A data structure that stores a deferred DOM operation.
// the first element is the function to call, and the rest of the array // 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[]] type Op = [Function, ...any[]]
// A "job" stands for a unit of work that needs to be performed. // 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) { function applyOp(op: Op) {
const fn = op[0] const fn = op[0]
// optimize for more common cases
// only patchData needs 8 arguments
if (op.length <= 3) {
fn(op[1], op[2], op[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])
}
} }