fix(teleport/css-v-bind): fix css v-bind in teleport in child component slot

This commit is contained in:
Evan You 2022-11-10 15:08:25 +08:00
parent 42239cf284
commit 11214eedd2
3 changed files with 40 additions and 12 deletions

View File

@ -223,7 +223,7 @@ export const TeleportImpl = {
} }
} }
updateCssVars(parentComponent, n2) updateCssVars(n2)
}, },
remove( remove(
@ -385,7 +385,7 @@ function hydrateTeleport(
) )
} }
} }
updateCssVars(parentComponent, vnode) updateCssVars(vnode)
} }
return vnode.anchor && nextSibling(vnode.anchor as Node) return vnode.anchor && nextSibling(vnode.anchor as Node)
} }
@ -396,19 +396,16 @@ export const Teleport = TeleportImpl as unknown as {
new (): { $props: VNodeProps & TeleportProps } new (): { $props: VNodeProps & TeleportProps }
} }
function updateCssVars( function updateCssVars(vnode: VNode) {
parentComponent: ComponentInternalInstance | null,
vnode: VNode
) {
// presence of .ut method indicates owner component uses css vars. // presence of .ut method indicates owner component uses css vars.
// code path here can assume browser environment. // code path here can assume browser environment.
if (parentComponent && parentComponent.ut) { const ctx = vnode.ctx
if (ctx && ctx.ut) {
let node = (vnode.children as VNode[])[0].el! let node = (vnode.children as VNode[])[0].el!
while (node !== vnode.targetAnchor) { while (node !== vnode.targetAnchor) {
if (node.nodeType === 1) if (node.nodeType === 1) node.setAttribute('data-v-owner', ctx.uid)
node.setAttribute('data-v-owner', parentComponent.uid)
node = node.nextSibling node = node.nextSibling
} }
parentComponent.ut() ctx.ut()
} }
} }

View File

@ -205,6 +205,11 @@ export interface VNode<
// application root node only // application root node only
appContext: AppContext | null appContext: AppContext | null
/**
* @internal lexical scope owner instance
*/
ctx: ComponentInternalInstance | null
/** /**
* @internal attached by v-memo * @internal attached by v-memo
*/ */
@ -439,7 +444,8 @@ function createBaseVNode(
patchFlag, patchFlag,
dynamicProps, dynamicProps,
dynamicChildren: null, dynamicChildren: null,
appContext: null appContext: null,
ctx: currentRenderingInstance
} as VNode } as VNode
if (needFullChildrenNormalization) { if (needFullChildrenNormalization) {
@ -661,7 +667,8 @@ export function cloneVNode<T, U>(
ssContent: vnode.ssContent && cloneVNode(vnode.ssContent), ssContent: vnode.ssContent && cloneVNode(vnode.ssContent),
ssFallback: vnode.ssFallback && cloneVNode(vnode.ssFallback), ssFallback: vnode.ssFallback && cloneVNode(vnode.ssFallback),
el: vnode.el, el: vnode.el,
anchor: vnode.anchor anchor: vnode.anchor,
ctx: vnode.ctx
} }
if (__COMPAT__) { if (__COMPAT__) {
defineLegacyVNodeProperties(cloned as VNode) defineLegacyVNodeProperties(cloned as VNode)

View File

@ -218,6 +218,30 @@ describe('useCssVars', () => {
} }
}) })
test('with teleport in child slot', async () => {
document.body.innerHTML = ''
const state = reactive({ color: 'red' })
const root = document.createElement('div')
const target = document.body
const Child: FunctionalComponent = (_, { slots }) => {
return h('div', slots.default && slots.default())
}
const App = {
setup() {
useCssVars(() => state)
return () => h(Child, () => [h(Teleport, { to: target }, [h('div')])])
}
}
render(h(App), root)
await nextTick()
for (const c of [].slice.call(target.children as any)) {
expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('red')
}
})
test('with teleport(change subTree)', async () => { test('with teleport(change subTree)', async () => {
document.body.innerHTML = '' document.body.innerHTML = ''
const state = reactive({ color: 'red' }) const state = reactive({ color: 'red' })