feat(compiler/slot): bail out of optimization mode for non-compiled slots

This commit is contained in:
Evan You 2019-10-03 15:09:09 -04:00
parent 05db2a9c6c
commit 227ad034f0
4 changed files with 23 additions and 10 deletions

View File

@ -58,7 +58,7 @@ export function shouldUpdateComponent(
): 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
if (patchFlag) { if (patchFlag > 0) {
if (patchFlag & PatchFlags.DYNAMIC_SLOTS) { if (patchFlag & PatchFlags.DYNAMIC_SLOTS) {
// slot content that references values that might have changed, // slot content that references values that might have changed,
// e.g. in a v-for // e.g. in a v-for

View File

@ -409,7 +409,7 @@ export function createRenderer<
invokeDirectiveHook(newProps.vnodeBeforeUpdate, parentComponent, n2, n1) invokeDirectiveHook(newProps.vnodeBeforeUpdate, parentComponent, n2, n1)
} }
if (patchFlag) { if (patchFlag > 0) {
// the presence of a patchFlag means this element's render code was // the presence of a patchFlag means this element's render code was
// generated by the compiler and can take the fast path. // generated by the compiler and can take the fast path.
// in this path old node and new node are guaranteed to have the same shape // in this path old node and new node are guaranteed to have the same shape
@ -1227,9 +1227,12 @@ export function createRenderer<
const prevShapeFlag = n1 ? n1.shapeFlag : 0 const prevShapeFlag = n1 ? n1.shapeFlag : 0
const c2 = n2.children const c2 = n2.children
// fast path
const { patchFlag, shapeFlag } = n2 const { patchFlag, shapeFlag } = n2
if (patchFlag) { if (patchFlag === PatchFlags.BAIL) {
optimized = false
}
// fast path
if (patchFlag > 0) {
if (patchFlag & PatchFlags.KEYED_FRAGMENT) { if (patchFlag & PatchFlags.KEYED_FRAGMENT) {
// this could be either fully-keyed or mixed (some keyed some not) // this could be either fully-keyed or mixed (some keyed some not)
// presence of patchFlag means children are guaranteed to be arrays // presence of patchFlag means children are guaranteed to be arrays

View File

@ -6,22 +6,24 @@ import {
Fragment, Fragment,
VNode VNode
} from '../vnode' } from '../vnode'
import { PatchFlags } from '@vue/shared'
export function renderSlot( export function renderSlot(
slots: Record<string, Slot>, slots: Record<string, Slot>,
key: string, name: string,
props: any = {}, props: any = {},
// this is not a user-facing function, so the fallback is always generated by // this is not a user-facing function, so the fallback is always generated by
// the compiler and gurunteed to be an array // the compiler and gurunteed to be an array
fallback?: VNodeChildren fallback?: VNodeChildren
): VNode { ): VNode {
const slot = slots[key] const slot = slots[name]
return ( return (
openBlock(), openBlock(),
createBlock( createBlock(
Fragment, Fragment,
{ key: props.key }, { key: props.key },
slot ? slot(props) : fallback || [] slot ? slot(props) : fallback || [],
slots._compiled ? 0 : PatchFlags.BAIL
) )
) )
} }

View File

@ -56,7 +56,13 @@ export const enum PatchFlags {
// Indicates a component with dynamic slots (e.g. slot that references a v-for // Indicates a component with dynamic slots (e.g. slot that references a v-for
// iterated value, or dynamic slot names). // iterated value, or dynamic slot names).
// Components with this flag are always force updated. // Components with this flag are always force updated.
DYNAMIC_SLOTS = 1 << 8 DYNAMIC_SLOTS = 1 << 8,
// A special flag that indicates that the diffing algorithm should bail out
// of optimized mode. This is only on block fragments created by renderSlot()
// when encountering non-compiler generated slots (i.e. manually written
// render functions, which should always be fully diffed)
BAIL = -1
} }
// runtime object for public consumption // runtime object for public consumption
@ -69,7 +75,8 @@ export const PublicPatchFlags = {
FULL_PROPS: PatchFlags.FULL_PROPS, FULL_PROPS: PatchFlags.FULL_PROPS,
KEYED_FRAGMENT: PatchFlags.KEYED_FRAGMENT, KEYED_FRAGMENT: PatchFlags.KEYED_FRAGMENT,
UNKEYED_FRAGMENT: PatchFlags.UNKEYED_FRAGMENT, UNKEYED_FRAGMENT: PatchFlags.UNKEYED_FRAGMENT,
DYNAMIC_SLOTS: PatchFlags.DYNAMIC_SLOTS DYNAMIC_SLOTS: PatchFlags.DYNAMIC_SLOTS,
BAIL: PatchFlags.BAIL
} }
// dev only flag -> name mapping // dev only flag -> name mapping
@ -82,5 +89,6 @@ export const PatchFlagNames = {
[PatchFlags.FULL_PROPS]: `FULL_PROPS`, [PatchFlags.FULL_PROPS]: `FULL_PROPS`,
[PatchFlags.KEYED_FRAGMENT]: `KEYED_FRAGMENT`, [PatchFlags.KEYED_FRAGMENT]: `KEYED_FRAGMENT`,
[PatchFlags.UNKEYED_FRAGMENT]: `UNKEYED_FRAGMENT`, [PatchFlags.UNKEYED_FRAGMENT]: `UNKEYED_FRAGMENT`,
[PatchFlags.DYNAMIC_SLOTS]: `DYNAMIC_SLOTS` [PatchFlags.DYNAMIC_SLOTS]: `DYNAMIC_SLOTS`,
[PatchFlags.BAIL]: `BAIL`
} }