refactor: fix implementation of SFC :slotted id handling

fix #2892
This commit is contained in:
Evan You
2021-03-05 11:10:06 -05:00
parent cc975c1292
commit aea88c3280
36 changed files with 723 additions and 457 deletions

View File

@@ -53,6 +53,10 @@ export function renderSlot(
? PatchFlags.STABLE_FRAGMENT
: PatchFlags.BAIL
)
// TODO (optimization) only add slot scope id if :slotted is used
if (rendered.scopeId) {
rendered.slotScopeIds = [rendered.scopeId + '-s']
}
isRenderingCompiledSlot--
return rendered
}

View File

@@ -1,10 +1,10 @@
import { currentRenderingInstance } from '../componentRenderUtils'
import {
currentInstance,
ConcreteComponent,
ComponentOptions,
getComponentName
} from '../component'
import { currentRenderingInstance } from '../componentRenderContext'
import { Directive } from '../directives'
import { camelize, capitalize, isString } from '@vue/shared'
import { warn } from '../warning'

View File

@@ -1,36 +0,0 @@
// SFC scoped style ID management.
// These are only used in esm-bundler builds, but since exports cannot be
// conditional, we can only drop inner implementations in non-bundler builds.
import { withCtx } from './withRenderContext'
export let currentScopeId: string | null = null
const scopeIdStack: string[] = []
/**
* @private
*/
export function pushScopeId(id: string) {
scopeIdStack.push((currentScopeId = id))
}
/**
* @private
*/
export function popScopeId() {
scopeIdStack.pop()
currentScopeId = scopeIdStack[scopeIdStack.length - 1] || null
}
/**
* @private
*/
export function withScopeId(id: string): <T extends Function>(fn: T) => T {
return ((fn: Function) =>
withCtx(function(this: any) {
pushScopeId(id)
const res = fn.apply(this, arguments)
popScopeId()
return res
})) as any
}

View File

@@ -1,37 +0,0 @@
import { Slot } from '../componentSlots'
import {
setCurrentRenderingInstance,
currentRenderingInstance
} from '../componentRenderUtils'
import { ComponentInternalInstance } from '../component'
import { isRenderingCompiledSlot } from './renderSlot'
import { closeBlock, openBlock } from '../vnode'
/**
* Wrap a slot function to memoize current rendering instance
* @private
*/
export function withCtx(
fn: Slot,
ctx: ComponentInternalInstance | null = currentRenderingInstance
) {
if (!ctx) return fn
const renderFnWithContext = (...args: any[]) => {
// If a user calls a compiled slot inside a template expression (#1745), it
// can mess up block tracking, so by default we need to push a null block to
// avoid that. This isn't necessary if rendering a compiled `<slot>`.
if (!isRenderingCompiledSlot) {
openBlock(true /* null block that disables tracking */)
}
const owner = currentRenderingInstance
setCurrentRenderingInstance(ctx)
const res = fn(...args)
setCurrentRenderingInstance(owner)
if (!isRenderingCompiledSlot) {
closeBlock()
}
return res
}
renderFnWithContext._c = true
return renderFnWithContext
}