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( export function shouldUpdateComponent(
prevVNode: VNode, prevVNode: VNode,
nextVNode: VNode nextVNode: VNode,
optimized?: boolean
): boolean { ): boolean {
const { props: prevProps, children: prevChildren } = prevVNode const { props: prevProps, children: prevChildren } = prevVNode
const { props: nextProps, children: nextChildren, patchFlag } = nextVNode 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 // this path is only taken by manually written render functions
// so presence of any children leads to a forced update // so presence of any children leads to a forced update
if (prevChildren != null || nextChildren != null) { if (prevChildren != null || nextChildren != null) {

View File

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

View File

@ -3,15 +3,13 @@ export {
openBlock, openBlock,
createBlock, createBlock,
createVNode, createVNode,
Text,
Empty,
Fragment, Fragment,
Portal Portal
} from './vnode' } from './vnode'
export { export { FunctionalComponent, createComponent } from './component'
ComponentOptions,
FunctionalComponent,
createComponent
} from './component'
export { Slot, Slots } from './componentSlots' 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 { ComponentInstance } from './component'
import { HostNode } from './createRenderer' import { HostNode } from './createRenderer'
import { RawSlots } from './componentSlots' import { RawSlots } from './componentSlots'
@ -85,14 +85,14 @@ export function createBlock(
export function createVNode( export function createVNode(
type: VNodeTypes, type: VNodeTypes,
props: { [key: string]: any } | null = null, props: { [key: string]: any } | null | 0 = null,
children: any = null, children: any = null,
patchFlag: number | null = null, patchFlag: number | null = null,
dynamicProps: string[] | null = null dynamicProps: string[] | null = null
): VNode { ): VNode {
const vnode: VNode = { const vnode: VNode = {
type, type,
props, props: props || null,
key: props && props.key, key: props && props.key,
children: normalizeChildren(children), children: normalizeChildren(children),
component: null, component: null,
@ -104,7 +104,13 @@ export function createVNode(
dynamicChildren: null dynamicChildren: null
} }
// presence of a patch flag indicates this node is dynamic // 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) trackDynamicNode(vnode)
} }
return vnode return vnode