refactor: improve fragment implementation
This commit is contained in:
parent
0ae6d8ab8b
commit
adfe0ee7bf
@ -1,5 +1,5 @@
|
|||||||
import { EMPTY_OBJ } from './utils'
|
import { EMPTY_OBJ } from './utils'
|
||||||
import { VNode, Slots, RenderNode, RenderFragment } from './vdom'
|
import { VNode, Slots, RenderNode, MountedVNode } from './vdom'
|
||||||
import {
|
import {
|
||||||
Data,
|
Data,
|
||||||
RenderFunction,
|
RenderFunction,
|
||||||
@ -30,7 +30,7 @@ export type ComponentType = ComponentClass | FunctionalComponent
|
|||||||
// to represent a mounted component
|
// to represent a mounted component
|
||||||
export interface MountedComponent<D = Data, P = Data>
|
export interface MountedComponent<D = Data, P = Data>
|
||||||
extends InternalComponent {
|
extends InternalComponent {
|
||||||
$vnode: VNode
|
$vnode: MountedVNode
|
||||||
$data: D
|
$data: D
|
||||||
$props: P
|
$props: P
|
||||||
$attrs: Data
|
$attrs: Data
|
||||||
@ -68,7 +68,7 @@ export interface MountedComponent<D = Data, P = Data>
|
|||||||
class InternalComponent {
|
class InternalComponent {
|
||||||
public static options?: ComponentOptions
|
public static options?: ComponentOptions
|
||||||
|
|
||||||
public get $el(): RenderNode | RenderFragment | null {
|
public get $el(): RenderNode | null {
|
||||||
return this.$vnode && this.$vnode.el
|
return this.$vnode && this.$vnode.el
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { VNodeFlags } from './flags'
|
import { VNodeFlags } from './flags'
|
||||||
import { EMPTY_OBJ } from './utils'
|
import { EMPTY_OBJ } from './utils'
|
||||||
import { h } from './h'
|
import { h } from './h'
|
||||||
import { VNode, createFragment } from './vdom'
|
import { VNode, MountedVNode, createFragment } from './vdom'
|
||||||
import { Component, MountedComponent, ComponentClass } from './component'
|
import { Component, MountedComponent, ComponentClass } from './component'
|
||||||
import { createTextVNode, cloneVNode } from './vdom'
|
import { createTextVNode, cloneVNode } from './vdom'
|
||||||
import { initializeState } from './componentState'
|
import { initializeState } from './componentState'
|
||||||
@ -22,7 +22,7 @@ export function createComponentInstance(
|
|||||||
parentComponent: MountedComponent | null
|
parentComponent: MountedComponent | null
|
||||||
): MountedComponent {
|
): MountedComponent {
|
||||||
const instance = (vnode.children = new Component()) as MountedComponent
|
const instance = (vnode.children = new Component()) as MountedComponent
|
||||||
instance.$parentVNode = vnode
|
instance.$parentVNode = vnode as MountedVNode
|
||||||
|
|
||||||
// renderProxy
|
// renderProxy
|
||||||
const proxy = (instance.$proxy = createRenderProxy(instance))
|
const proxy = (instance.$proxy = createRenderProxy(instance))
|
||||||
@ -53,7 +53,7 @@ export function createComponentInstance(
|
|||||||
return instance as MountedComponent
|
return instance as MountedComponent
|
||||||
}
|
}
|
||||||
|
|
||||||
export function renderInstanceRoot(instance: MountedComponent) {
|
export function renderInstanceRoot(instance: MountedComponent): VNode {
|
||||||
let vnode
|
let vnode
|
||||||
try {
|
try {
|
||||||
vnode = instance.render.call(
|
vnode = instance.render.call(
|
||||||
|
@ -5,13 +5,11 @@ import { EMPTY_OBJ, reservedPropRE, lis } from './utils'
|
|||||||
import {
|
import {
|
||||||
VNode,
|
VNode,
|
||||||
MountedVNode,
|
MountedVNode,
|
||||||
MountedVNodes,
|
|
||||||
RenderNode,
|
RenderNode,
|
||||||
createTextVNode,
|
createTextVNode,
|
||||||
cloneVNode,
|
cloneVNode,
|
||||||
Ref,
|
Ref,
|
||||||
VNodeChildren,
|
VNodeChildren
|
||||||
RenderFragment
|
|
||||||
} from './vdom'
|
} from './vdom'
|
||||||
import {
|
import {
|
||||||
MountedComponent,
|
MountedComponent,
|
||||||
@ -34,7 +32,6 @@ interface NodeOps {
|
|||||||
setText: (node: any, text: string) => void
|
setText: (node: any, text: string) => void
|
||||||
appendChild: (parent: any, child: any) => void
|
appendChild: (parent: any, child: any) => void
|
||||||
insertBefore: (parent: any, child: any, ref: any) => void
|
insertBefore: (parent: any, child: any, ref: any) => void
|
||||||
replaceChild: (parent: any, oldChild: any, newChild: any) => void
|
|
||||||
removeChild: (parent: any, child: any) => void
|
removeChild: (parent: any, child: any) => void
|
||||||
clearContent: (node: any) => void
|
clearContent: (node: any) => void
|
||||||
parentNode: (node: any) => any
|
parentNode: (node: any) => any
|
||||||
@ -75,7 +72,6 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
setText: platformSetText,
|
setText: platformSetText,
|
||||||
appendChild: platformAppendChild,
|
appendChild: platformAppendChild,
|
||||||
insertBefore: platformInsertBefore,
|
insertBefore: platformInsertBefore,
|
||||||
replaceChild: platformReplaceChild,
|
|
||||||
removeChild: platformRemoveChild,
|
removeChild: platformRemoveChild,
|
||||||
clearContent: platformClearContent,
|
clearContent: platformClearContent,
|
||||||
parentNode: platformParentNode,
|
parentNode: platformParentNode,
|
||||||
@ -86,78 +82,19 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
teardownVNode
|
teardownVNode
|
||||||
} = options
|
} = options
|
||||||
|
|
||||||
// Node operations (shimmed to handle virtual fragments) ---------------------
|
|
||||||
|
|
||||||
function appendChild(container: RenderNode, el: RenderNode | RenderFragment) {
|
|
||||||
if (el.$f) {
|
|
||||||
for (let i = 0; i < el.children.length; i++) {
|
|
||||||
appendChild(container, el.children[i])
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
platformAppendChild(container, el)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function insertBefore(
|
|
||||||
container: RenderNode,
|
|
||||||
el: RenderNode | RenderFragment,
|
|
||||||
ref: RenderNode | RenderFragment
|
|
||||||
) {
|
|
||||||
while (ref.$f) {
|
|
||||||
ref = ref.children[0]
|
|
||||||
}
|
|
||||||
if (el.$f) {
|
|
||||||
for (let i = 0; i < el.children.length; i++) {
|
|
||||||
insertBefore(container, el.children[i], ref)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
platformInsertBefore(container, el, ref)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeChild(container: RenderNode, el: RenderNode | RenderFragment) {
|
|
||||||
if (el.$f) {
|
|
||||||
for (let i = 0; i < el.children.length; i++) {
|
|
||||||
removeChild(container, el.children[i])
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
platformRemoveChild(container, el)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function replaceChild(
|
|
||||||
container: RenderNode,
|
|
||||||
oldChild: RenderNode | RenderFragment,
|
|
||||||
newChild: RenderNode | RenderFragment
|
|
||||||
) {
|
|
||||||
if (oldChild.$f || newChild.$f) {
|
|
||||||
insertOrAppend(container, newChild, oldChild)
|
|
||||||
removeChild(container, oldChild)
|
|
||||||
} else {
|
|
||||||
platformReplaceChild(container, oldChild, newChild)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function parentNode(el: RenderNode | RenderFragment): RenderNode {
|
|
||||||
while (el.$f) {
|
|
||||||
el = el.children[0]
|
|
||||||
}
|
|
||||||
return platformParentNode(el)
|
|
||||||
}
|
|
||||||
|
|
||||||
function insertOrAppend(
|
function insertOrAppend(
|
||||||
container: RenderNode,
|
container: RenderNode,
|
||||||
newNode: RenderNode | RenderFragment,
|
newNode: RenderNode,
|
||||||
refNode: RenderNode | RenderFragment | null
|
refNode: RenderNode | null
|
||||||
) {
|
) {
|
||||||
if (refNode === null) {
|
if (refNode === null) {
|
||||||
appendChild(container, newNode)
|
platformAppendChild(container, newNode)
|
||||||
} else {
|
} else {
|
||||||
insertBefore(container, newNode, refNode)
|
platformInsertBefore(container, newNode, refNode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// lifecycle lifecycleHooks -----------------------------------------------------------
|
// Lifecycle Hooks -----------------------------------------------------------
|
||||||
|
|
||||||
const lifecycleHooks: Function[] = []
|
const lifecycleHooks: Function[] = []
|
||||||
const vnodeUpdatedHooks: Function[] = []
|
const vnodeUpdatedHooks: Function[] = []
|
||||||
@ -176,7 +113,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
container: RenderNode | null,
|
container: RenderNode | null,
|
||||||
parentComponent: MountedComponent | null,
|
parentComponent: MountedComponent | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
endNode: RenderNode | RenderFragment | null
|
endNode: RenderNode | null
|
||||||
) {
|
) {
|
||||||
const { flags } = vnode
|
const { flags } = vnode
|
||||||
if (flags & VNodeFlags.ELEMENT) {
|
if (flags & VNodeFlags.ELEMENT) {
|
||||||
@ -197,7 +134,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
container: RenderNode | null,
|
container: RenderNode | null,
|
||||||
parentComponent: MountedComponent | null,
|
parentComponent: MountedComponent | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
endNode: RenderNode | RenderFragment | null
|
endNode: RenderNode | null
|
||||||
) {
|
) {
|
||||||
for (let i = 0; i < children.length; i++) {
|
for (let i = 0; i < children.length; i++) {
|
||||||
let child = children[i]
|
let child = children[i]
|
||||||
@ -213,7 +150,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
container: RenderNode | null,
|
container: RenderNode | null,
|
||||||
parentComponent: MountedComponent | null,
|
parentComponent: MountedComponent | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
endNode: RenderNode | RenderFragment | null
|
endNode: RenderNode | null
|
||||||
) {
|
) {
|
||||||
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
|
||||||
@ -264,19 +201,18 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
container: RenderNode | null,
|
container: RenderNode | null,
|
||||||
parentComponent: MountedComponent | null,
|
parentComponent: MountedComponent | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
endNode: RenderNode | RenderFragment | null
|
endNode: RenderNode | null
|
||||||
) {
|
) {
|
||||||
let el: RenderNode | RenderFragment
|
|
||||||
const { flags, tag, data, slots } = vnode
|
const { flags, tag, data, slots } = vnode
|
||||||
if (flags & VNodeFlags.COMPONENT_STATEFUL) {
|
if (flags & VNodeFlags.COMPONENT_STATEFUL) {
|
||||||
if (flags & VNodeFlags.COMPONENT_STATEFUL_KEPT_ALIVE) {
|
if (flags & VNodeFlags.COMPONENT_STATEFUL_KEPT_ALIVE) {
|
||||||
// kept-alive
|
// kept-alive
|
||||||
el = activateComponentInstance(vnode)
|
activateComponentInstance(vnode)
|
||||||
} else {
|
} else {
|
||||||
el = mountComponentInstance(
|
mountComponentInstance(
|
||||||
vnode,
|
vnode,
|
||||||
tag as ComponentClass,
|
tag as ComponentClass,
|
||||||
null,
|
container,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
isSVG,
|
isSVG,
|
||||||
endNode
|
endNode
|
||||||
@ -292,24 +228,20 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
attrs,
|
attrs,
|
||||||
render.inheritAttrs
|
render.inheritAttrs
|
||||||
))
|
))
|
||||||
mount(subTree, null, parentComponent, isSVG, endNode)
|
mount(subTree, container, parentComponent, isSVG, endNode)
|
||||||
el = vnode.el = subTree.el as RenderNode
|
vnode.el = subTree.el as RenderNode
|
||||||
}
|
|
||||||
if (container != null) {
|
|
||||||
insertOrAppend(container, el, endNode)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mountText(
|
function mountText(
|
||||||
vnode: VNode,
|
vnode: VNode,
|
||||||
container: RenderNode | null,
|
container: RenderNode | null,
|
||||||
endNode: RenderNode | RenderFragment | null
|
endNode: RenderNode | null
|
||||||
): RenderNode {
|
) {
|
||||||
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)
|
insertOrAppend(container, el, endNode)
|
||||||
}
|
}
|
||||||
return el
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function mountFragment(
|
function mountFragment(
|
||||||
@ -317,36 +249,29 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
container: RenderNode | null,
|
container: RenderNode | null,
|
||||||
parentComponent: MountedComponent | null,
|
parentComponent: MountedComponent | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
endNode: RenderNode | RenderFragment | null
|
endNode: RenderNode | null
|
||||||
): RenderFragment {
|
) {
|
||||||
const { children, childFlags } = vnode
|
const { children, childFlags } = vnode
|
||||||
const fragment: RenderFragment = (vnode.el = {
|
switch (childFlags) {
|
||||||
$f: true,
|
case ChildrenFlags.SINGLE_VNODE:
|
||||||
children: []
|
mount(children as VNode, container, parentComponent, isSVG, endNode)
|
||||||
})
|
vnode.el = (children as MountedVNode).el
|
||||||
const fragmentChildren = fragment.children
|
break
|
||||||
if (childFlags & ChildrenFlags.SINGLE_VNODE) {
|
case ChildrenFlags.NO_CHILDREN:
|
||||||
mount(children as VNode, container, parentComponent, isSVG, endNode)
|
const placeholder = createTextVNode('')
|
||||||
fragmentChildren.push((children as VNode).el as RenderNode)
|
mountText(placeholder, container, null)
|
||||||
} else if (childFlags & ChildrenFlags.MULTIPLE_VNODES) {
|
vnode.el = placeholder.el
|
||||||
mountArrayChildren(
|
break
|
||||||
children as VNode[],
|
default:
|
||||||
container,
|
mountArrayChildren(
|
||||||
parentComponent,
|
children as VNode[],
|
||||||
isSVG,
|
container,
|
||||||
endNode
|
parentComponent,
|
||||||
)
|
isSVG,
|
||||||
for (let i = 0; i < (children as MountedVNodes).length; i++) {
|
endNode
|
||||||
fragmentChildren.push((children as MountedVNodes)[i].el)
|
)
|
||||||
}
|
vnode.el = (children as MountedVNode[])[0].el
|
||||||
} else {
|
|
||||||
// ensure at least one children so that it can be used as a ref node
|
|
||||||
// during insertions
|
|
||||||
const vnode = createTextVNode('')
|
|
||||||
mountText(vnode, container, endNode)
|
|
||||||
fragmentChildren.push(vnode.el as RenderNode)
|
|
||||||
}
|
}
|
||||||
return fragment
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function mountPortal(
|
function mountPortal(
|
||||||
@ -381,7 +306,9 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
if (ref) {
|
if (ref) {
|
||||||
mountRef(ref, target as RenderNode)
|
mountRef(ref, target as RenderNode)
|
||||||
}
|
}
|
||||||
vnode.el = mountText(createTextVNode(''), container, null)
|
const placeholder = createTextVNode('')
|
||||||
|
mountText(placeholder, container, null)
|
||||||
|
vnode.el = placeholder.el
|
||||||
}
|
}
|
||||||
|
|
||||||
// patching ------------------------------------------------------------------
|
// patching ------------------------------------------------------------------
|
||||||
@ -411,7 +338,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function patch(
|
function patch(
|
||||||
prevVNode: VNode,
|
prevVNode: MountedVNode,
|
||||||
nextVNode: VNode,
|
nextVNode: VNode,
|
||||||
container: RenderNode,
|
container: RenderNode,
|
||||||
parentComponent: MountedComponent | null,
|
parentComponent: MountedComponent | null,
|
||||||
@ -436,7 +363,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function patchElement(
|
function patchElement(
|
||||||
prevVNode: VNode,
|
prevVNode: MountedVNode,
|
||||||
nextVNode: VNode,
|
nextVNode: VNode,
|
||||||
container: RenderNode,
|
container: RenderNode,
|
||||||
parentComponent: MountedComponent | null,
|
parentComponent: MountedComponent | null,
|
||||||
@ -450,7 +377,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const el = (nextVNode.el = prevVNode.el) as RenderNode
|
const el = (nextVNode.el = prevVNode.el)
|
||||||
const prevData = prevVNode.data
|
const prevData = prevVNode.data
|
||||||
const nextData = nextVNode.data
|
const nextData = nextVNode.data
|
||||||
|
|
||||||
@ -509,7 +436,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function patchComponent(
|
function patchComponent(
|
||||||
prevVNode: VNode,
|
prevVNode: MountedVNode,
|
||||||
nextVNode: VNode,
|
nextVNode: VNode,
|
||||||
container: RenderNode,
|
container: RenderNode,
|
||||||
parentComponent: MountedComponent | null,
|
parentComponent: MountedComponent | null,
|
||||||
@ -531,7 +458,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function patchStatefulComponent(prevVNode: VNode, nextVNode: VNode) {
|
function patchStatefulComponent(prevVNode: MountedVNode, nextVNode: VNode) {
|
||||||
const { childFlags: prevChildFlags } = prevVNode
|
const { childFlags: prevChildFlags } = prevVNode
|
||||||
const {
|
const {
|
||||||
data: nextData,
|
data: nextData,
|
||||||
@ -542,7 +469,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
const instance = (nextVNode.children =
|
const instance = (nextVNode.children =
|
||||||
prevVNode.children) as MountedComponent
|
prevVNode.children) as MountedComponent
|
||||||
instance.$slots = nextSlots || EMPTY_OBJ
|
instance.$slots = nextSlots || EMPTY_OBJ
|
||||||
instance.$parentVNode = nextVNode
|
instance.$parentVNode = nextVNode as MountedVNode
|
||||||
|
|
||||||
// Update props. This will trigger child update if necessary.
|
// Update props. This will trigger child update if necessary.
|
||||||
if (nextData !== null) {
|
if (nextData !== null) {
|
||||||
@ -565,7 +492,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function patchFunctionalComponent(
|
function patchFunctionalComponent(
|
||||||
prevVNode: VNode,
|
prevVNode: MountedVNode,
|
||||||
nextVNode: VNode,
|
nextVNode: VNode,
|
||||||
container: RenderNode,
|
container: RenderNode,
|
||||||
parentComponent: MountedComponent | null,
|
parentComponent: MountedComponent | null,
|
||||||
@ -575,7 +502,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
const { data: prevData, slots: prevSlots } = prevVNode
|
const { data: prevData, slots: prevSlots } = prevVNode
|
||||||
const { data: nextData, slots: nextSlots } = nextVNode
|
const { data: nextData, slots: nextSlots } = nextVNode
|
||||||
const render = nextVNode.tag as FunctionalComponent
|
const render = nextVNode.tag as FunctionalComponent
|
||||||
const prevTree = prevVNode.children as VNode
|
const prevTree = prevVNode.children as MountedVNode
|
||||||
|
|
||||||
let shouldUpdate = true
|
let shouldUpdate = true
|
||||||
if (render.pure && prevSlots == null && nextSlots == null) {
|
if (render.pure && prevSlots == null && nextSlots == null) {
|
||||||
@ -599,7 +526,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function patchFragment(
|
function patchFragment(
|
||||||
prevVNode: VNode,
|
prevVNode: MountedVNode,
|
||||||
nextVNode: VNode,
|
nextVNode: VNode,
|
||||||
container: RenderNode,
|
container: RenderNode,
|
||||||
parentComponent: MountedComponent | null,
|
parentComponent: MountedComponent | null,
|
||||||
@ -607,11 +534,8 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
) {
|
) {
|
||||||
// determine the tail node of the previous fragment,
|
// determine the tail node of the previous fragment,
|
||||||
// then retrieve its next sibling to use as the end node for patchChildren.
|
// then retrieve its next sibling to use as the end node for patchChildren.
|
||||||
let prevElement = prevVNode.el as RenderNode | RenderFragment
|
const endNode = platformNextSibling(getVNodeLastEl(prevVNode))
|
||||||
while (prevElement.$f) {
|
const { childFlags, children } = nextVNode
|
||||||
prevElement = prevElement.children[prevElement.children.length - 1]
|
|
||||||
}
|
|
||||||
const { children, childFlags } = nextVNode
|
|
||||||
patchChildren(
|
patchChildren(
|
||||||
prevVNode.childFlags,
|
prevVNode.childFlags,
|
||||||
childFlags,
|
childFlags,
|
||||||
@ -620,24 +544,38 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
container,
|
container,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
isSVG,
|
isSVG,
|
||||||
platformNextSibling(prevElement)
|
endNode
|
||||||
)
|
)
|
||||||
nextVNode.el = prevVNode.el as RenderFragment
|
switch (childFlags) {
|
||||||
const fragmentChildren: (
|
case ChildrenFlags.SINGLE_VNODE:
|
||||||
| RenderNode
|
nextVNode.el = (children as MountedVNode).el
|
||||||
| RenderFragment)[] = (nextVNode.el.children = [])
|
break
|
||||||
if (childFlags & ChildrenFlags.SINGLE_VNODE) {
|
case ChildrenFlags.NO_CHILDREN:
|
||||||
fragmentChildren.push((children as MountedVNode).el)
|
nextVNode.el = prevVNode.el
|
||||||
} else if (childFlags & ChildrenFlags.MULTIPLE_VNODES) {
|
break
|
||||||
for (let i = 0; i < (children as MountedVNodes).length; i++) {
|
default:
|
||||||
fragmentChildren.push((children as MountedVNodes)[i].el)
|
nextVNode.el = (children as MountedVNode[])[0].el
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fragmentChildren.push(mountText(createTextVNode(''), null, null))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function patchText(prevVNode: VNode, nextVNode: VNode) {
|
function getVNodeLastEl(vnode: MountedVNode): RenderNode {
|
||||||
|
const { el, flags, children, childFlags } = vnode
|
||||||
|
if (flags & VNodeFlags.FRAGMENT) {
|
||||||
|
if (childFlags & ChildrenFlags.SINGLE_VNODE) {
|
||||||
|
return getVNodeLastEl(children as MountedVNode)
|
||||||
|
} else if (childFlags & ChildrenFlags.MULTIPLE_VNODES) {
|
||||||
|
return getVNodeLastEl(
|
||||||
|
(children as MountedVNode[])[(children as MountedVNode[]).length - 1]
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return el
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return el
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function patchText(prevVNode: MountedVNode, nextVNode: VNode) {
|
||||||
const el = (nextVNode.el = prevVNode.el) as RenderNode
|
const el = (nextVNode.el = prevVNode.el) as RenderNode
|
||||||
const nextText = nextVNode.children
|
const nextText = nextVNode.children
|
||||||
if (nextText !== prevVNode.children) {
|
if (nextText !== prevVNode.children) {
|
||||||
@ -646,7 +584,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function patchPortal(
|
function patchPortal(
|
||||||
prevVNode: VNode,
|
prevVNode: MountedVNode,
|
||||||
nextVNode: VNode,
|
nextVNode: VNode,
|
||||||
parentComponent: MountedComponent | null
|
parentComponent: MountedComponent | null
|
||||||
) {
|
) {
|
||||||
@ -667,13 +605,13 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
if (nextContainer !== prevContainer) {
|
if (nextContainer !== prevContainer) {
|
||||||
switch (nextVNode.childFlags) {
|
switch (nextVNode.childFlags) {
|
||||||
case ChildrenFlags.SINGLE_VNODE:
|
case ChildrenFlags.SINGLE_VNODE:
|
||||||
appendChild(nextContainer, (nextChildren as MountedVNode).el)
|
moveVNode(nextChildren as MountedVNode, nextContainer, null)
|
||||||
break
|
break
|
||||||
case ChildrenFlags.NO_CHILDREN:
|
case ChildrenFlags.NO_CHILDREN:
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
for (let i = 0; i < (nextChildren as MountedVNodes).length; i++) {
|
for (let i = 0; i < (nextChildren as MountedVNode[]).length; i++) {
|
||||||
appendChild(nextContainer, (nextChildren as MountedVNodes)[i].el)
|
moveVNode((nextChildren as MountedVNode[])[i], nextContainer, null)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -681,19 +619,15 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function replaceVNode(
|
function replaceVNode(
|
||||||
prevVNode: VNode,
|
prevVNode: MountedVNode,
|
||||||
nextVNode: VNode,
|
nextVNode: VNode,
|
||||||
container: RenderNode,
|
container: RenderNode,
|
||||||
parentComponent: MountedComponent | null,
|
parentComponent: MountedComponent | null,
|
||||||
isSVG: boolean
|
isSVG: boolean
|
||||||
) {
|
) {
|
||||||
unmount(prevVNode)
|
const refNode = platformNextSibling(getVNodeLastEl(prevVNode))
|
||||||
mount(nextVNode, null, parentComponent, isSVG, null)
|
removeVNode(prevVNode, container)
|
||||||
replaceChild(
|
mount(nextVNode, container, parentComponent, isSVG, refNode)
|
||||||
container,
|
|
||||||
prevVNode.el as RenderNode | RenderFragment,
|
|
||||||
nextVNode.el as RenderNode
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function patchChildren(
|
function patchChildren(
|
||||||
@ -704,14 +638,14 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
container: RenderNode,
|
container: RenderNode,
|
||||||
parentComponent: MountedComponent | null,
|
parentComponent: MountedComponent | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
endNode: RenderNode | RenderFragment | null
|
endNode: RenderNode | null
|
||||||
) {
|
) {
|
||||||
switch (prevChildFlags) {
|
switch (prevChildFlags) {
|
||||||
case ChildrenFlags.SINGLE_VNODE:
|
case ChildrenFlags.SINGLE_VNODE:
|
||||||
switch (nextChildFlags) {
|
switch (nextChildFlags) {
|
||||||
case ChildrenFlags.SINGLE_VNODE:
|
case ChildrenFlags.SINGLE_VNODE:
|
||||||
patch(
|
patch(
|
||||||
prevChildren as VNode,
|
prevChildren as MountedVNode,
|
||||||
nextChildren as VNode,
|
nextChildren as VNode,
|
||||||
container,
|
container,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
@ -719,10 +653,10 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
)
|
)
|
||||||
break
|
break
|
||||||
case ChildrenFlags.NO_CHILDREN:
|
case ChildrenFlags.NO_CHILDREN:
|
||||||
remove(prevChildren as VNode, container)
|
removeVNode(prevChildren as MountedVNode, container)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
remove(prevChildren as VNode, container)
|
removeVNode(prevChildren as MountedVNode, container)
|
||||||
mountArrayChildren(
|
mountArrayChildren(
|
||||||
nextChildren as VNode[],
|
nextChildren as VNode[],
|
||||||
container,
|
container,
|
||||||
@ -760,7 +694,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
default:
|
default:
|
||||||
// MULTIPLE_CHILDREN
|
// MULTIPLE_CHILDREN
|
||||||
if (nextChildFlags === ChildrenFlags.SINGLE_VNODE) {
|
if (nextChildFlags === ChildrenFlags.SINGLE_VNODE) {
|
||||||
removeAll(prevChildren as MountedVNodes, container, endNode)
|
removeChildren(prevChildren as MountedVNode[], container, endNode)
|
||||||
mount(
|
mount(
|
||||||
nextChildren as VNode,
|
nextChildren as VNode,
|
||||||
container,
|
container,
|
||||||
@ -769,7 +703,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
endNode
|
endNode
|
||||||
)
|
)
|
||||||
} else if (nextChildFlags === ChildrenFlags.NO_CHILDREN) {
|
} else if (nextChildFlags === ChildrenFlags.NO_CHILDREN) {
|
||||||
removeAll(prevChildren as MountedVNodes, container, endNode)
|
removeChildren(prevChildren as MountedVNode[], container, endNode)
|
||||||
} else {
|
} else {
|
||||||
const prevLength = (prevChildren as VNode[]).length
|
const prevLength = (prevChildren as VNode[]).length
|
||||||
const nextLength = (nextChildren as VNode[]).length
|
const nextLength = (nextChildren as VNode[]).length
|
||||||
@ -784,13 +718,13 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else if (nextLength === 0) {
|
} else if (nextLength === 0) {
|
||||||
removeAll(prevChildren as MountedVNodes, container, endNode)
|
removeChildren(prevChildren as MountedVNode[], container, endNode)
|
||||||
} else if (
|
} else if (
|
||||||
prevChildFlags === ChildrenFlags.KEYED_VNODES &&
|
prevChildFlags === ChildrenFlags.KEYED_VNODES &&
|
||||||
nextChildFlags === ChildrenFlags.KEYED_VNODES
|
nextChildFlags === ChildrenFlags.KEYED_VNODES
|
||||||
) {
|
) {
|
||||||
patchKeyedChildren(
|
patchKeyedChildren(
|
||||||
prevChildren as VNode[],
|
prevChildren as MountedVNode[],
|
||||||
nextChildren as VNode[],
|
nextChildren as VNode[],
|
||||||
container,
|
container,
|
||||||
prevLength,
|
prevLength,
|
||||||
@ -801,7 +735,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
patchNonKeyedChildren(
|
patchNonKeyedChildren(
|
||||||
prevChildren as VNode[],
|
prevChildren as MountedVNode[],
|
||||||
nextChildren as VNode[],
|
nextChildren as VNode[],
|
||||||
container,
|
container,
|
||||||
prevLength,
|
prevLength,
|
||||||
@ -817,14 +751,14 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function patchNonKeyedChildren(
|
function patchNonKeyedChildren(
|
||||||
prevChildren: VNode[],
|
prevChildren: MountedVNode[],
|
||||||
nextChildren: VNode[],
|
nextChildren: VNode[],
|
||||||
container: RenderNode,
|
container: RenderNode,
|
||||||
prevLength: number,
|
prevLength: number,
|
||||||
nextLength: number,
|
nextLength: number,
|
||||||
parentComponent: MountedComponent | null,
|
parentComponent: MountedComponent | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
endNode: RenderNode | RenderFragment | null
|
endNode: RenderNode | null
|
||||||
) {
|
) {
|
||||||
const commonLength = prevLength > nextLength ? nextLength : prevLength
|
const commonLength = prevLength > nextLength ? nextLength : prevLength
|
||||||
let i = 0
|
let i = 0
|
||||||
@ -837,7 +771,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
nextChildren[i] = nextChild = cloneVNode(nextChild)
|
nextChildren[i] = nextChild = cloneVNode(nextChild)
|
||||||
}
|
}
|
||||||
patch(prevChild, nextChild, container, parentComponent, isSVG)
|
patch(prevChild, nextChild, container, parentComponent, isSVG)
|
||||||
prevChildren[i] = nextChild
|
prevChildren[i] = nextChild as MountedVNode
|
||||||
}
|
}
|
||||||
if (prevLength < nextLength) {
|
if (prevLength < nextLength) {
|
||||||
for (i = commonLength; i < nextLength; i++) {
|
for (i = commonLength; i < nextLength; i++) {
|
||||||
@ -849,20 +783,20 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
}
|
}
|
||||||
} else if (prevLength > nextLength) {
|
} else if (prevLength > nextLength) {
|
||||||
for (i = commonLength; i < prevLength; i++) {
|
for (i = commonLength; i < prevLength; i++) {
|
||||||
remove(prevChildren[i], container)
|
removeVNode(prevChildren[i], container)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function patchKeyedChildren(
|
function patchKeyedChildren(
|
||||||
prevChildren: VNode[],
|
prevChildren: MountedVNode[],
|
||||||
nextChildren: VNode[],
|
nextChildren: VNode[],
|
||||||
container: RenderNode,
|
container: RenderNode,
|
||||||
prevLength: number,
|
prevLength: number,
|
||||||
nextLength: number,
|
nextLength: number,
|
||||||
parentComponent: MountedComponent | null,
|
parentComponent: MountedComponent | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
endNode: RenderNode | RenderFragment | null
|
endNode: RenderNode | null
|
||||||
) {
|
) {
|
||||||
let prevEnd = prevLength - 1
|
let prevEnd = prevLength - 1
|
||||||
let nextEnd = nextLength - 1
|
let nextEnd = nextLength - 1
|
||||||
@ -879,7 +813,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
nextChildren[j] = nextVNode = cloneVNode(nextVNode)
|
nextChildren[j] = nextVNode = cloneVNode(nextVNode)
|
||||||
}
|
}
|
||||||
patch(prevVNode, nextVNode, container, parentComponent, isSVG)
|
patch(prevVNode, nextVNode, container, parentComponent, isSVG)
|
||||||
prevChildren[j] = nextVNode
|
prevChildren[j] = nextVNode as MountedVNode
|
||||||
j++
|
j++
|
||||||
if (j > prevEnd || j > nextEnd) {
|
if (j > prevEnd || j > nextEnd) {
|
||||||
break outer
|
break outer
|
||||||
@ -897,7 +831,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
nextChildren[nextEnd] = nextVNode = cloneVNode(nextVNode)
|
nextChildren[nextEnd] = nextVNode = cloneVNode(nextVNode)
|
||||||
}
|
}
|
||||||
patch(prevVNode, nextVNode, container, parentComponent, isSVG)
|
patch(prevVNode, nextVNode, container, parentComponent, isSVG)
|
||||||
prevChildren[prevEnd] = nextVNode
|
prevChildren[prevEnd] = nextVNode as MountedVNode
|
||||||
prevEnd--
|
prevEnd--
|
||||||
nextEnd--
|
nextEnd--
|
||||||
if (j > prevEnd || j > nextEnd) {
|
if (j > prevEnd || j > nextEnd) {
|
||||||
@ -924,7 +858,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
}
|
}
|
||||||
} else if (j > nextEnd) {
|
} else if (j > nextEnd) {
|
||||||
while (j <= prevEnd) {
|
while (j <= prevEnd) {
|
||||||
remove(prevChildren[j++], container)
|
removeVNode(prevChildren[j++], container)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let prevStart = j
|
let prevStart = j
|
||||||
@ -953,7 +887,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
if (canRemoveWholeContent) {
|
if (canRemoveWholeContent) {
|
||||||
canRemoveWholeContent = false
|
canRemoveWholeContent = false
|
||||||
while (i > prevStart) {
|
while (i > prevStart) {
|
||||||
remove(prevChildren[prevStart++], container)
|
removeVNode(prevChildren[prevStart++], container)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pos > j) {
|
if (pos > j) {
|
||||||
@ -970,10 +904,10 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!canRemoveWholeContent && j > nextEnd) {
|
if (!canRemoveWholeContent && j > nextEnd) {
|
||||||
remove(prevVNode, container)
|
removeVNode(prevVNode, container)
|
||||||
}
|
}
|
||||||
} else if (!canRemoveWholeContent) {
|
} else if (!canRemoveWholeContent) {
|
||||||
remove(prevVNode, container)
|
removeVNode(prevVNode, container)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -995,7 +929,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
if (canRemoveWholeContent) {
|
if (canRemoveWholeContent) {
|
||||||
canRemoveWholeContent = false
|
canRemoveWholeContent = false
|
||||||
while (i > prevStart) {
|
while (i > prevStart) {
|
||||||
remove(prevChildren[prevStart++], container)
|
removeVNode(prevChildren[prevStart++], container)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nextVNode = nextChildren[j]
|
nextVNode = nextChildren[j]
|
||||||
@ -1011,16 +945,16 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
patch(prevVNode, nextVNode, container, parentComponent, isSVG)
|
patch(prevVNode, nextVNode, container, parentComponent, isSVG)
|
||||||
patched++
|
patched++
|
||||||
} else if (!canRemoveWholeContent) {
|
} else if (!canRemoveWholeContent) {
|
||||||
remove(prevVNode, container)
|
removeVNode(prevVNode, container)
|
||||||
}
|
}
|
||||||
} else if (!canRemoveWholeContent) {
|
} else if (!canRemoveWholeContent) {
|
||||||
remove(prevVNode, container)
|
removeVNode(prevVNode, container)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// fast-path: if nothing patched remove all old and add all new
|
// fast-path: if nothing patched remove all old and add all new
|
||||||
if (canRemoveWholeContent) {
|
if (canRemoveWholeContent) {
|
||||||
removeAll(prevChildren as MountedVNodes, container, endNode)
|
removeChildren(prevChildren as MountedVNode[], container, endNode)
|
||||||
mountArrayChildren(
|
mountArrayChildren(
|
||||||
nextChildren,
|
nextChildren,
|
||||||
container,
|
container,
|
||||||
@ -1051,9 +985,9 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
pos = i + nextStart
|
pos = i + nextStart
|
||||||
nextVNode = nextChildren[pos]
|
nextVNode = nextChildren[pos]
|
||||||
nextPos = pos + 1
|
nextPos = pos + 1
|
||||||
insertOrAppend(
|
moveVNode(
|
||||||
|
nextVNode as MountedVNode,
|
||||||
container,
|
container,
|
||||||
nextVNode.el as RenderNode | RenderFragment,
|
|
||||||
nextPos < nextLength ? nextChildren[nextPos].el : endNode
|
nextPos < nextLength ? nextChildren[nextPos].el : endNode
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@ -1085,9 +1019,32 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function moveVNode(
|
||||||
|
vnode: MountedVNode,
|
||||||
|
container: RenderNode,
|
||||||
|
refNode: RenderNode | null
|
||||||
|
) {
|
||||||
|
const { flags, childFlags, children } = vnode
|
||||||
|
if (flags & VNodeFlags.FRAGMENT) {
|
||||||
|
switch (childFlags) {
|
||||||
|
case ChildrenFlags.SINGLE_VNODE:
|
||||||
|
moveVNode(children as MountedVNode, container, refNode)
|
||||||
|
break
|
||||||
|
case ChildrenFlags.NO_CHILDREN:
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
for (let i = 0; i < (children as MountedVNode[]).length; i++) {
|
||||||
|
moveVNode((children as MountedVNode[])[i], container, refNode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
insertOrAppend(container, vnode.el as RenderNode, refNode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// unmounting ----------------------------------------------------------------
|
// unmounting ----------------------------------------------------------------
|
||||||
|
|
||||||
function unmount(vnode: VNode) {
|
function unmount(vnode: MountedVNode) {
|
||||||
const { flags, data, children, childFlags, ref } = vnode
|
const { flags, data, children, childFlags, ref } = vnode
|
||||||
const isElement = flags & VNodeFlags.ELEMENT
|
const isElement = flags & VNodeFlags.ELEMENT
|
||||||
if (isElement || flags & VNodeFlags.FRAGMENT) {
|
if (isElement || flags & VNodeFlags.FRAGMENT) {
|
||||||
@ -1109,13 +1066,17 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
unmountComponentInstance(children as MountedComponent)
|
unmountComponentInstance(children as MountedComponent)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unmount(children as VNode)
|
unmount(children as MountedVNode)
|
||||||
}
|
}
|
||||||
} else if (flags & VNodeFlags.PORTAL) {
|
} else if (flags & VNodeFlags.PORTAL) {
|
||||||
if (childFlags & ChildrenFlags.MULTIPLE_VNODES) {
|
if (childFlags & ChildrenFlags.MULTIPLE_VNODES) {
|
||||||
removeAll(children as MountedVNodes, vnode.tag as RenderNode, null)
|
removeChildren(
|
||||||
|
children as MountedVNode[],
|
||||||
|
vnode.tag as RenderNode,
|
||||||
|
null
|
||||||
|
)
|
||||||
} else if (childFlags === ChildrenFlags.SINGLE_VNODE) {
|
} else if (childFlags === ChildrenFlags.SINGLE_VNODE) {
|
||||||
remove(children as VNode, vnode.tag as RenderNode)
|
removeVNode(children as MountedVNode, vnode.tag as RenderNode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ref) {
|
if (ref) {
|
||||||
@ -1125,37 +1086,53 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
|
|
||||||
function unmountChildren(children: VNodeChildren, childFlags: ChildrenFlags) {
|
function unmountChildren(children: VNodeChildren, childFlags: ChildrenFlags) {
|
||||||
if (childFlags & ChildrenFlags.MULTIPLE_VNODES) {
|
if (childFlags & ChildrenFlags.MULTIPLE_VNODES) {
|
||||||
unmountArrayChildren(children as VNode[])
|
unmountArrayChildren(children as MountedVNode[])
|
||||||
} else if (childFlags === ChildrenFlags.SINGLE_VNODE) {
|
} else if (childFlags === ChildrenFlags.SINGLE_VNODE) {
|
||||||
unmount(children as VNode)
|
unmount(children as MountedVNode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function unmountArrayChildren(children: VNode[]) {
|
function unmountArrayChildren(children: MountedVNode[]) {
|
||||||
for (let i = 0; i < children.length; i++) {
|
for (let i = 0; i < children.length; i++) {
|
||||||
unmount(children[i])
|
unmount(children[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function remove(vnode: VNode, container: RenderNode) {
|
function removeVNode(vnode: MountedVNode, container: RenderNode) {
|
||||||
unmount(vnode)
|
unmount(vnode)
|
||||||
if (container && vnode.el) {
|
const { el, flags, children, childFlags } = vnode
|
||||||
removeChild(container, vnode.el)
|
if (container && el) {
|
||||||
vnode.el = null
|
if (flags & VNodeFlags.FRAGMENT) {
|
||||||
|
switch (childFlags) {
|
||||||
|
case ChildrenFlags.SINGLE_VNODE:
|
||||||
|
removeVNode(children as MountedVNode, container)
|
||||||
|
break
|
||||||
|
case ChildrenFlags.NO_CHILDREN:
|
||||||
|
platformRemoveChild(container, el)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
for (let i = 0; i < (children as MountedVNode[]).length; i++) {
|
||||||
|
removeVNode((children as MountedVNode[])[i], container)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
platformRemoveChild(container, el)
|
||||||
|
}
|
||||||
|
;(vnode as any).el = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeAll(
|
function removeChildren(
|
||||||
children: MountedVNodes,
|
children: MountedVNode[],
|
||||||
container: RenderNode,
|
container: RenderNode,
|
||||||
ref: RenderNode | RenderFragment | null
|
refNode: RenderNode | null
|
||||||
) {
|
) {
|
||||||
unmountArrayChildren(children)
|
unmountArrayChildren(children)
|
||||||
if (ref === null) {
|
if (refNode === null) {
|
||||||
platformClearContent(container)
|
platformClearContent(container)
|
||||||
} else {
|
} else {
|
||||||
for (let i = 0; i < children.length; i++) {
|
for (let i = 0; i < children.length; i++) {
|
||||||
removeChild(container, children[i].el as RenderNode | RenderFragment)
|
removeVNode(children[i], container)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1168,7 +1145,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
container: RenderNode | null,
|
container: RenderNode | null,
|
||||||
parentComponent: MountedComponent | null,
|
parentComponent: MountedComponent | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
endNode: RenderNode | RenderFragment | null
|
endNode: RenderNode | null
|
||||||
): RenderNode {
|
): RenderNode {
|
||||||
// a vnode may already have an instance if this is a compat call with
|
// a vnode may already have an instance if this is a compat call with
|
||||||
// new Vue()
|
// new Vue()
|
||||||
@ -1195,10 +1172,10 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (instance._mounted) {
|
if (instance._mounted) {
|
||||||
updateComponentInstance(instance, container, isSVG)
|
updateComponentInstance(instance, isSVG)
|
||||||
} else {
|
} else {
|
||||||
// this will be executed synchronously right here
|
// this will be executed synchronously right here
|
||||||
instance.$vnode = renderInstanceRoot(instance)
|
instance.$vnode = renderInstanceRoot(instance) as MountedVNode
|
||||||
mount(instance.$vnode, container, instance, isSVG, endNode)
|
mount(instance.$vnode, container, instance, isSVG, endNode)
|
||||||
parentVNode.el = instance.$vnode.el
|
parentVNode.el = instance.$vnode.el
|
||||||
instance._mounted = true
|
instance._mounted = true
|
||||||
@ -1229,20 +1206,17 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateComponentInstance(
|
function updateComponentInstance(instance: MountedComponent, isSVG: boolean) {
|
||||||
instance: MountedComponent,
|
|
||||||
container: RenderNode | null,
|
|
||||||
isSVG: boolean
|
|
||||||
) {
|
|
||||||
const prevVNode = instance.$vnode
|
const prevVNode = instance.$vnode
|
||||||
|
|
||||||
if (instance.beforeUpdate) {
|
if (instance.beforeUpdate) {
|
||||||
instance.beforeUpdate.call(instance.$proxy, prevVNode)
|
instance.beforeUpdate.call(instance.$proxy, prevVNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
const nextVNode = (instance.$vnode = renderInstanceRoot(instance))
|
const nextVNode = (instance.$vnode = renderInstanceRoot(
|
||||||
container =
|
instance
|
||||||
container || parentNode(prevVNode.el as RenderNode | RenderFragment)
|
) as MountedVNode)
|
||||||
|
const container = platformParentNode(prevVNode.el) as RenderNode
|
||||||
patch(prevVNode, nextVNode, container, instance, isSVG)
|
patch(prevVNode, nextVNode, container, instance, isSVG)
|
||||||
const el = nextVNode.el as RenderNode
|
const el = nextVNode.el as RenderNode
|
||||||
|
|
||||||
@ -1299,13 +1273,12 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
|
|
||||||
// Keep Alive ----------------------------------------------------------------
|
// Keep Alive ----------------------------------------------------------------
|
||||||
|
|
||||||
function activateComponentInstance(vnode: VNode): RenderNode {
|
function activateComponentInstance(vnode: VNode) {
|
||||||
const instance = vnode.children as MountedComponent
|
const instance = vnode.children as MountedComponent
|
||||||
const el = (vnode.el = instance.$el)
|
vnode.el = instance.$el
|
||||||
lifecycleHooks.push(() => {
|
lifecycleHooks.push(() => {
|
||||||
callActivatedHook(instance, true)
|
callActivatedHook(instance, true)
|
||||||
})
|
})
|
||||||
return el as RenderNode
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function callActivatedHook(instance: MountedComponent, asRoot: boolean) {
|
function callActivatedHook(instance: MountedComponent, asRoot: boolean) {
|
||||||
@ -1373,7 +1346,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
patch(prevVNode, vnode, container, null, false)
|
patch(prevVNode, vnode, container, null, false)
|
||||||
container.vnode = vnode
|
container.vnode = vnode
|
||||||
} else {
|
} else {
|
||||||
remove(prevVNode, container)
|
removeVNode(prevVNode, container)
|
||||||
container.vnode = null
|
container.vnode = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,11 +15,6 @@ export interface RenderNode {
|
|||||||
$f: false
|
$f: false
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RenderFragment {
|
|
||||||
children: (RenderNode | RenderFragment)[]
|
|
||||||
$f: true
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface VNode {
|
export interface VNode {
|
||||||
_isVNode: true
|
_isVNode: true
|
||||||
flags: VNodeFlags
|
flags: VNodeFlags
|
||||||
@ -31,18 +26,16 @@ export interface VNode {
|
|||||||
ref: Ref | null
|
ref: Ref | null
|
||||||
slots: Slots | null
|
slots: Slots | null
|
||||||
// only on mounted nodes
|
// only on mounted nodes
|
||||||
el: RenderNode | RenderFragment | null
|
el: RenderNode | null
|
||||||
// only on mounted component root nodes
|
// only on mounted component root nodes
|
||||||
// points to component node in parent tree
|
// points to component node in parent tree
|
||||||
parentVNode: VNode | null
|
parentVNode: VNode | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MountedVNode extends VNode {
|
export interface MountedVNode extends VNode {
|
||||||
el: RenderNode | RenderFragment
|
el: RenderNode
|
||||||
}
|
}
|
||||||
|
|
||||||
export type MountedVNodes = MountedVNode[]
|
|
||||||
|
|
||||||
export interface VNodeData {
|
export interface VNodeData {
|
||||||
key?: Key | null
|
key?: Key | null
|
||||||
ref?: Ref | null
|
ref?: Ref | null
|
||||||
|
Loading…
x
Reference in New Issue
Block a user