fix(runtime-core): avoid unmount teleport's children multiple times (#3499)
fix #3497
This commit is contained in:
parent
117a61bc17
commit
3736496006
@ -8,7 +8,9 @@ import {
|
|||||||
ref,
|
ref,
|
||||||
nextTick,
|
nextTick,
|
||||||
markRaw,
|
markRaw,
|
||||||
defineComponent
|
defineComponent,
|
||||||
|
withDirectives,
|
||||||
|
createApp
|
||||||
} from '@vue/runtime-test'
|
} from '@vue/runtime-test'
|
||||||
import { createVNode, Fragment } from '../../src/vnode'
|
import { createVNode, Fragment } from '../../src/vnode'
|
||||||
import { compile, render as domRender } from 'vue'
|
import { compile, render as domRender } from 'vue'
|
||||||
@ -432,4 +434,42 @@ describe('renderer: teleport', () => {
|
|||||||
`"<div>teleported</div><span>false</span><!--v-if-->"`
|
`"<div>teleported</div><span>false</span><!--v-if-->"`
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// #3497
|
||||||
|
test(`the dir hooks of the Teleport's children should be called correctly`, async () => {
|
||||||
|
const target = nodeOps.createElement('div')
|
||||||
|
const root = nodeOps.createElement('div')
|
||||||
|
const toggle = ref(true)
|
||||||
|
const dir = {
|
||||||
|
mounted: jest.fn(),
|
||||||
|
unmounted: jest.fn()
|
||||||
|
}
|
||||||
|
|
||||||
|
const app = createApp({
|
||||||
|
setup() {
|
||||||
|
return () => {
|
||||||
|
return toggle.value
|
||||||
|
? h(Teleport, { to: target }, [
|
||||||
|
withDirectives(h('div', ['foo']), [[dir]])
|
||||||
|
])
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
app.mount(root)
|
||||||
|
|
||||||
|
expect(serializeInner(root)).toMatchInlineSnapshot(
|
||||||
|
`"<!--teleport start--><!--teleport end-->"`
|
||||||
|
)
|
||||||
|
expect(serializeInner(target)).toMatchInlineSnapshot(`"<div>foo</div>"`)
|
||||||
|
expect(dir.mounted).toHaveBeenCalledTimes(1)
|
||||||
|
expect(dir.unmounted).toHaveBeenCalledTimes(0)
|
||||||
|
|
||||||
|
toggle.value = false
|
||||||
|
await nextTick()
|
||||||
|
expect(serializeInner(root)).toMatchInlineSnapshot(`"<!---->"`)
|
||||||
|
expect(serializeInner(target)).toMatchInlineSnapshot(`""`)
|
||||||
|
expect(dir.mounted).toHaveBeenCalledTimes(1)
|
||||||
|
expect(dir.unmounted).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -2096,7 +2096,16 @@ function baseCreateRenderer(
|
|||||||
invokeDirectiveHook(vnode, null, parentComponent, 'beforeUnmount')
|
invokeDirectiveHook(vnode, null, parentComponent, 'beforeUnmount')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (shapeFlag & ShapeFlags.TELEPORT) {
|
||||||
|
;(vnode.type as typeof TeleportImpl).remove(
|
||||||
|
vnode,
|
||||||
|
parentComponent,
|
||||||
|
parentSuspense,
|
||||||
|
optimized,
|
||||||
|
internals,
|
||||||
|
doRemove
|
||||||
|
)
|
||||||
|
} else if (
|
||||||
dynamicChildren &&
|
dynamicChildren &&
|
||||||
// #1153: fast path should not be taken for non-stable (v-for) fragments
|
// #1153: fast path should not be taken for non-stable (v-for) fragments
|
||||||
(type !== Fragment ||
|
(type !== Fragment ||
|
||||||
@ -2119,17 +2128,6 @@ function baseCreateRenderer(
|
|||||||
unmountChildren(children as VNode[], parentComponent, parentSuspense)
|
unmountChildren(children as VNode[], parentComponent, parentSuspense)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shapeFlag & ShapeFlags.TELEPORT) {
|
|
||||||
;(vnode.type as typeof TeleportImpl).remove(
|
|
||||||
vnode,
|
|
||||||
parentComponent,
|
|
||||||
parentSuspense,
|
|
||||||
optimized,
|
|
||||||
internals,
|
|
||||||
doRemove
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (doRemove) {
|
if (doRemove) {
|
||||||
remove(vnode)
|
remove(vnode)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user