wip: always track component nodes

This commit is contained in:
Evan You 2019-06-01 02:14:49 +08:00
parent da5edd3429
commit 05556eacb2
4 changed files with 21 additions and 14 deletions

View File

@ -163,7 +163,8 @@ export function renderComponentRoot(instance: ComponentInstance): VNode {
export function shouldUpdateComponent(
prevVNode: VNode,
nextVNode: VNode
nextVNode: VNode,
optimized?: boolean
): boolean {
const { props: prevProps, children: prevChildren } = prevVNode
const { props: nextProps, children: nextChildren, patchFlag } = nextVNode
@ -185,7 +186,7 @@ export function shouldUpdateComponent(
}
}
}
} else {
} else if (!optimized) {
// this path is only taken by manually written render functions
// so presence of any children leads to a forced update
if (prevChildren != null || nextChildren != null) {

View File

@ -139,7 +139,7 @@ export function createRenderer(options: RendererOptions) {
// TODO warn invalid node type
debugger
}
processComponent(n1, n2, container, anchor)
processComponent(n1, n2, container, anchor, optimized)
}
break
}
@ -426,16 +426,18 @@ export function createRenderer(options: RendererOptions) {
n1: VNode | null,
n2: VNode,
container: HostNode,
anchor?: HostNode
anchor?: HostNode,
optimized?: boolean
) {
if (n1 == null) {
mountComponent(n2, container, anchor)
} else {
const instance = (n2.component = n1.component) as ComponentInstance
if (shouldUpdateComponent(n1, n2)) {
if (shouldUpdateComponent(n1, n2, optimized)) {
instance.next = n2
instance.update()
} else {
n2.component = n1.component
n2.el = n1.el
}
}

View File

@ -3,15 +3,13 @@ export {
openBlock,
createBlock,
createVNode,
Text,
Empty,
Fragment,
Portal
} from './vnode'
export {
ComponentOptions,
FunctionalComponent,
createComponent
} from './component'
export { FunctionalComponent, createComponent } from './component'
export { Slot, Slots } from './componentSlots'

View File

@ -1,4 +1,4 @@
import { isArray, isFunction, isString, EMPTY_ARR } from '@vue/shared'
import { isArray, isFunction, isString, isObject, EMPTY_ARR } from '@vue/shared'
import { ComponentInstance } from './component'
import { HostNode } from './createRenderer'
import { RawSlots } from './componentSlots'
@ -85,14 +85,14 @@ export function createBlock(
export function createVNode(
type: VNodeTypes,
props: { [key: string]: any } | null = null,
props: { [key: string]: any } | null | 0 = null,
children: any = null,
patchFlag: number | null = null,
dynamicProps: string[] | null = null
): VNode {
const vnode: VNode = {
type,
props,
props: props || null,
key: props && props.key,
children: normalizeChildren(children),
component: null,
@ -104,7 +104,13 @@ export function createVNode(
dynamicChildren: null
}
// presence of a patch flag indicates this node is dynamic
if (shouldTrack && patchFlag != null) {
// component nodes also should always be tracked, because even if the
// component doesn't need to update, it needs to persist the instance on to
// the next vnode so that it can be properly unmounted later.
if (
shouldTrack &&
(patchFlag != null || isObject(type) || isFunction(type))
) {
trackDynamicNode(vnode)
}
return vnode