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
} = 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,11 +425,10 @@ export function createRenderer(options: RendererOptions) {
nextVNode: VNode,
isSVG: boolean
) {
if (reservedPropRE.test(key)) {
return
}
platformPatchData(
typeof el === 'function' ? el() : el,
if (!reservedPropRE.test(key)) {
queueNodeOp([
platformPatchData,
el,
key,
prevValue,
nextValue,
@ -424,7 +436,8 @@ export function createRenderer(options: RendererOptions) {
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)
}
}

View File

@ -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]
// 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])
}
}