Skip to content

Commit 8cfc10a

Browse files
authored
fix(ssr): ensure empty slots render as a comment node in Transition (#13396)
close #13394
1 parent 7f29943 commit 8cfc10a

File tree

3 files changed

+125
-8
lines changed

3 files changed

+125
-8
lines changed

‎packages/runtime-core/__tests__/hydration.spec.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1740,6 +1740,35 @@ describe('SSR hydration', () => {
17401740
expect(`mismatch`).not.toHaveBeenWarned()
17411741
})
17421742

1743+
// #13394
1744+
test('transition appear work with empty content', async () => {
1745+
const show = ref(true)
1746+
const { vnode, container } = mountWithHydration(
1747+
`<template><!----></template>`,
1748+
function (this: any) {
1749+
return h(
1750+
Transition,
1751+
{ appear: true },
1752+
{
1753+
default: () =>
1754+
show.value
1755+
? renderSlot(this.$slots, 'default')
1756+
: createTextVNode('foo'),
1757+
},
1758+
)
1759+
},
1760+
)
1761+
1762+
// empty slot render as a comment node
1763+
expect(container.firstChild!.nodeType).toBe(Node.COMMENT_NODE)
1764+
expect(vnode.el).toBe(container.firstChild)
1765+
expect(`mismatch`).not.toHaveBeenWarned()
1766+
1767+
show.value = false
1768+
await nextTick()
1769+
expect(container.innerHTML).toBe('foo')
1770+
})
1771+
17431772
test('transition appear with v-if', () => {
17441773
const show = false
17451774
const { vnode, container } = mountWithHydration(

‎packages/server-renderer/__tests__/ssrSlot.spec.ts

Lines changed: 86 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -111,26 +111,106 @@ describe('ssr: slot', () => {
111111
})
112112

113113
test('transition slot', async () => {
114+
const ReusableTransition = {
115+
template: `<transition><slot/></transition>`,
116+
}
117+
118+
const ReusableTransitionWithAppear = {
119+
template: `<transition appear><slot/></transition>`,
120+
}
121+
114122
expect(
115123
await renderToString(
116124
createApp({
117125
components: {
118-
one: {
119-
template: `<transition><slot/></transition>`,
120-
},
126+
one: ReusableTransition,
121127
},
122128
template: `<one><div v-if="false">foo</div></one>`,
123129
}),
124130
),
125131
).toBe(`<!---->`)
126132

133+
expect(await renderToString(createApp(ReusableTransition))).toBe(`<!---->`)
134+
135+
expect(await renderToString(createApp(ReusableTransitionWithAppear))).toBe(
136+
`<template><!----></template>`,
137+
)
138+
127139
expect(
128140
await renderToString(
129141
createApp({
130142
components: {
131-
one: {
132-
template: `<transition><slot/></transition>`,
133-
},
143+
one: ReusableTransition,
144+
},
145+
template: `<one><slot/></one>`,
146+
}),
147+
),
148+
).toBe(`<!---->`)
149+
150+
expect(
151+
await renderToString(
152+
createApp({
153+
components: {
154+
one: ReusableTransitionWithAppear,
155+
},
156+
template: `<one><slot/></one>`,
157+
}),
158+
),
159+
).toBe(`<template><!----></template>`)
160+
161+
expect(
162+
await renderToString(
163+
createApp({
164+
render() {
165+
return h(ReusableTransition, null, {
166+
default: () => null,
167+
})
168+
},
169+
}),
170+
),
171+
).toBe(`<!---->`)
172+
173+
expect(
174+
await renderToString(
175+
createApp({
176+
render() {
177+
return h(ReusableTransitionWithAppear, null, {
178+
default: () => null,
179+
})
180+
},
181+
}),
182+
),
183+
).toBe(`<template><!----></template>`)
184+
185+
expect(
186+
await renderToString(
187+
createApp({
188+
render() {
189+
return h(ReusableTransitionWithAppear, null, {
190+
default: () => [],
191+
})
192+
},
193+
}),
194+
),
195+
).toBe(`<template><!----></template>`)
196+
197+
expect(
198+
await renderToString(
199+
createApp({
200+
render() {
201+
return h(ReusableTransition, null, {
202+
default: () => [],
203+
})
204+
},
205+
}),
206+
),
207+
).toBe(`<!---->`)
208+
209+
expect(
210+
await renderToString(
211+
createApp({
212+
components: {
213+
one: ReusableTransition,
134214
},
135215
template: `<one><div v-if="true">foo</div></one>`,
136216
}),

‎packages/server-renderer/src/helpers/ssrRenderSlot.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ export function ssrRenderSlotInner(
7474
)
7575
} else if (fallbackRenderFn) {
7676
fallbackRenderFn()
77+
} else if (transition) {
78+
push(`<!---->`)
7779
}
7880
} else {
7981
// ssr slot.
@@ -110,13 +112,19 @@ export function ssrRenderSlotInner(
110112
end--
111113
}
112114

113-
for (let i = start; i < end; i++) {
114-
push(slotBuffer[i])
115+
if (start < end) {
116+
for (let i = start; i < end; i++) {
117+
push(slotBuffer[i])
118+
}
119+
} else if (transition) {
120+
push(`<!---->`)
115121
}
116122
}
117123
}
118124
} else if (fallbackRenderFn) {
119125
fallbackRenderFn()
126+
} else if (transition) {
127+
push(`<!---->`)
120128
}
121129
}
122130

0 commit comments

Comments
 (0)