Skip to content

Commit d15dce3

Browse files
authored
fix(teleport): handle deferred teleport updates before and after mount (#13350)
close #13349
1 parent 163b365 commit d15dce3

File tree

2 files changed

+60
-3
lines changed

2 files changed

+60
-3
lines changed

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

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
render,
1717
serialize,
1818
serializeInner,
19+
useModel,
1920
withDirectives,
2021
} from '@vue/runtime-test'
2122
import {
@@ -144,6 +145,62 @@ describe('renderer: teleport', () => {
144145
`"<!--teleport start--><!--teleport end--><div>Footer</div><div id="targetId"><div>bar</div></div>"`,
145146
)
146147
})
148+
149+
// #13349
150+
test('handle deferred teleport updates before and after mount', async () => {
151+
const root = document.createElement('div')
152+
document.body.appendChild(root)
153+
154+
const show = ref(false)
155+
const data2 = ref('2')
156+
const data3 = ref('3')
157+
158+
const Comp = {
159+
props: {
160+
modelValue: {},
161+
modelModifiers: {},
162+
},
163+
emits: ['update:modelValue'],
164+
setup(props: any) {
165+
const data2 = useModel(props, 'modelValue')
166+
data2.value = '2+'
167+
return () => h('span')
168+
},
169+
}
170+
171+
createDOMApp({
172+
setup() {
173+
setTimeout(() => (show.value = true), 5)
174+
setTimeout(() => (data3.value = '3+'), 10)
175+
},
176+
render() {
177+
return h(Fragment, null, [
178+
h('span', { id: 'targetId001' }),
179+
show.value
180+
? h(Fragment, null, [
181+
h(Teleport, { to: '#targetId001', defer: true }, [
182+
createTextVNode(String(data3.value)),
183+
]),
184+
h(Comp, {
185+
modelValue: data2.value,
186+
'onUpdate:modelValue': (event: any) =>
187+
(data2.value = event),
188+
}),
189+
])
190+
: createCommentVNode('v-if'),
191+
])
192+
},
193+
}).mount(root)
194+
195+
expect(root.innerHTML).toMatchInlineSnapshot(
196+
`"<span id="targetId001"></span><!--v-if-->"`,
197+
)
198+
199+
await new Promise(r => setTimeout(r, 10))
200+
expect(root.innerHTML).toMatchInlineSnapshot(
201+
`"<span id="targetId001">3+</span><!--teleport start--><!--teleport end--><span></span>"`,
202+
)
203+
})
147204
})
148205

149206
function runSharedTests(deferMode: boolean) {

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,15 +164,16 @@ export const TeleportImpl = {
164164
}
165165

166166
if (isTeleportDeferred(n2.props)) {
167+
n2.el!.__isMounted = false
167168
queuePostRenderEffect(() => {
168169
mountToTarget()
169-
n2.el!.__isMounted = true
170+
delete n2.el!.__isMounted
170171
}, parentSuspense)
171172
} else {
172173
mountToTarget()
173174
}
174175
} else {
175-
if (isTeleportDeferred(n2.props) && !n1.el!.__isMounted) {
176+
if (isTeleportDeferred(n2.props) && n1.el!.__isMounted === false) {
176177
queuePostRenderEffect(() => {
177178
TeleportImpl.process(
178179
n1,
@@ -186,7 +187,6 @@ export const TeleportImpl = {
186187
optimized,
187188
internals,
188189
)
189-
delete n1.el!.__isMounted
190190
}, parentSuspense)
191191
return
192192
}

0 commit comments

Comments
 (0)