fix(runtime-core): avoid manual slot invocation in template expressions interfering with block tracking

fix #1745
This commit is contained in:
Evan You
2020-08-06 10:16:13 -04:00
parent 233d191d0d
commit 791eff3dfb
4 changed files with 62 additions and 19 deletions

View File

@@ -10,6 +10,8 @@ import {
import { PatchFlags, SlotFlags } from '@vue/shared'
import { warn } from '../warning'
export let isRenderingTemplateSlot = false
/**
* Compiler runtime helper for rendering `<slot/>`
* @private
@@ -33,15 +35,20 @@ export function renderSlot(
slot = () => []
}
return (
openBlock(),
createBlock(
Fragment,
{ key: props.key },
slot ? slot(props) : fallback ? fallback() : [],
(slots as RawSlots)._ === SlotFlags.STABLE
? PatchFlags.STABLE_FRAGMENT
: PatchFlags.BAIL
)
)
// a compiled slot disables block tracking by default to avoid manual
// invocation interfering with template-based block tracking, but in
// `renderSlot` we can be sure that it's template-based so we can force
// enable it.
isRenderingTemplateSlot = true
const rendered = (openBlock(),
createBlock(
Fragment,
{ key: props.key },
slot ? slot(props) : fallback ? fallback() : [],
(slots as RawSlots)._ === SlotFlags.STABLE
? PatchFlags.STABLE_FRAGMENT
: PatchFlags.BAIL
))
isRenderingTemplateSlot = false
return rendered
}

View File

@@ -4,6 +4,7 @@ import {
currentRenderingInstance
} from '../componentRenderUtils'
import { ComponentInternalInstance } from '../component'
import { setBlockTracking } from '../vnode'
/**
* Wrap a slot function to memoize current rendering instance
@@ -15,10 +16,15 @@ export function withCtx(
) {
if (!ctx) return fn
return function renderFnWithContext() {
// By default, compiled slots disables block tracking since the user may
// call it inside a template expression (#1745). It should only track when
// it's called by a template `<slot>`.
setBlockTracking(-1)
const owner = currentRenderingInstance
setCurrentRenderingInstance(ctx)
const res = fn.apply(null, arguments as any)
setCurrentRenderingInstance(owner)
setBlockTracking(1)
return res
}
}