wip: component update fast path

This commit is contained in:
Evan You 2019-05-30 16:00:42 +08:00
parent b82b7af29b
commit 200c035862
3 changed files with 39 additions and 30 deletions

View File

@ -3,6 +3,7 @@ import { ReactiveEffect, UnwrapValue, observable } from '@vue/observer'
import { isFunction, EMPTY_OBJ } from '@vue/shared'
import { RenderProxyHandlers } from './componentProxy'
import { ComponentPropsOptions, PropValidator } from './componentProps'
import { PROPS, SLOTS } from './patchFlags'
export type Data = { [key: string]: any }
@ -167,36 +168,43 @@ export function shouldUpdateComponent(
nextVNode: VNode
): boolean {
const { props: prevProps } = prevVNode
const { props: nextProps } = nextVNode
// TODO handle slots
// If has different slots content, or has non-compiled slots,
// the child needs to be force updated.
// if (
// prevChildFlags !== nextChildFlags ||
// (nextChildFlags & ChildrenFlags.DYNAMIC_SLOTS) > 0
// ) {
// return true
// }
if (prevProps === nextProps) {
return false
}
if (prevProps === null) {
return nextProps !== null
}
if (nextProps === null) {
return prevProps !== null
}
const nextKeys = Object.keys(nextProps)
if (nextKeys.length !== Object.keys(prevProps).length) {
return true
}
for (let i = 0; i < nextKeys.length; i++) {
const key = nextKeys[i]
if (nextProps[key] !== prevProps[key]) {
const { props: nextProps, patchFlag } = nextVNode
if (patchFlag !== null) {
if (patchFlag & SLOTS) {
// slot content that references values that might have changed,
// e.g. in a v-for
return true
}
if (patchFlag & PROPS) {
const dynamicProps = nextVNode.dynamicProps as string[]
for (let i = 0; i < dynamicProps.length; i++) {
const key = dynamicProps[i]
if ((nextProps as any)[key] !== (prevProps as any)[key]) {
return true
}
}
}
} else {
// TODO handle slots
if (prevProps === nextProps) {
return false
}
if (prevProps === null) {
return nextProps !== null
}
if (nextProps === null) {
return prevProps !== null
}
const nextKeys = Object.keys(nextProps)
if (nextKeys.length !== Object.keys(prevProps).length) {
return true
}
for (let i = 0; i < nextKeys.length; i++) {
const key = nextKeys[i]
if (nextProps[key] !== prevProps[key]) {
return true
}
}
}
return false
}

View File

@ -4,3 +4,4 @@ export const STYLE = 1 << 2
export const PROPS = 1 << 3
export const KEYED = 1 << 4
export const UNKEYED = 1 << 5
export const SLOTS = 1 << 6 // component only

View File

@ -1,4 +1,4 @@
import { isArray, isFunction, EMPTY_ARR } from '@vue/shared'
import { isArray, EMPTY_ARR } from '@vue/shared'
import { ComponentInstance } from './component'
import { HostNode } from './createRenderer'
@ -87,7 +87,7 @@ export function createVNode(
dynamicProps,
dynamicChildren: null
}
if (shouldTrack && (patchFlag != null || isFunction(type))) {
if (shouldTrack && patchFlag != null) {
trackDynamicNode(vnode)
}
return vnode