Skip to content

Commit 8bff142

Browse files
authoredNov 14, 2024··
fix(teleport): handle deferred teleport update before mounted (#12168)
close #12161
1 parent c4312f9 commit 8bff142

File tree

2 files changed

+65
-1
lines changed

2 files changed

+65
-1
lines changed
 

‎packages/runtime-core/__tests__/components/Teleport.spec.ts

+43
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,49 @@ describe('renderer: teleport', () => {
8787
`</div>`,
8888
)
8989
})
90+
91+
test('update before mounted with defer', async () => {
92+
const root = document.createElement('div')
93+
document.body.appendChild(root)
94+
95+
const show = ref(false)
96+
const foo = ref('foo')
97+
const Header = {
98+
props: { foo: String },
99+
setup(props: any) {
100+
return () => h('div', props.foo)
101+
},
102+
}
103+
const Footer = {
104+
setup() {
105+
foo.value = 'bar'
106+
return () => h('div', 'Footer')
107+
},
108+
}
109+
createDOMApp({
110+
render() {
111+
return show.value
112+
? [
113+
h(
114+
Teleport,
115+
{ to: '#targetId', defer: true },
116+
h(Header, { foo: foo.value }),
117+
),
118+
h(Footer),
119+
h('div', { id: 'targetId' }),
120+
]
121+
: [h('div')]
122+
},
123+
}).mount(root)
124+
125+
expect(root.innerHTML).toMatchInlineSnapshot(`"<div></div>"`)
126+
127+
show.value = true
128+
await nextTick()
129+
expect(root.innerHTML).toMatchInlineSnapshot(
130+
`"<!--teleport start--><!--teleport end--><div>Footer</div><div id="targetId"><div>bar</div></div>"`,
131+
)
132+
})
90133
})
91134

92135
function runSharedTests(deferMode: boolean) {

‎packages/runtime-core/src/components/Teleport.ts

+22-1
Original file line numberDiff line numberDiff line change
@@ -164,11 +164,32 @@ export const TeleportImpl = {
164164
}
165165

166166
if (isTeleportDeferred(n2.props)) {
167-
queuePostRenderEffect(mountToTarget, parentSuspense)
167+
queuePostRenderEffect(() => {
168+
mountToTarget()
169+
n2.el!.__isMounted = true
170+
}, parentSuspense)
168171
} else {
169172
mountToTarget()
170173
}
171174
} else {
175+
if (isTeleportDeferred(n2.props) && !n1.el!.__isMounted) {
176+
queuePostRenderEffect(() => {
177+
TeleportImpl.process(
178+
n1,
179+
n2,
180+
container,
181+
anchor,
182+
parentComponent,
183+
parentSuspense,
184+
namespace,
185+
slotScopeIds,
186+
optimized,
187+
internals,
188+
)
189+
delete n1.el!.__isMounted
190+
}, parentSuspense)
191+
return
192+
}
172193
// update content
173194
n2.el = n1.el
174195
n2.targetStart = n1.targetStart

0 commit comments

Comments
 (0)
Please sign in to comment.