Skip to content

Commit

Permalink
fix(runtime-core): avoid unmount teleport's children multiple times (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
HcySunYang authored Mar 29, 2021
1 parent 117a61b commit 3736496
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 13 deletions.
42 changes: 41 additions & 1 deletion packages/runtime-core/__tests__/components/Teleport.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import {
ref,
nextTick,
markRaw,
defineComponent
defineComponent,
withDirectives,
createApp
} from '@vue/runtime-test'
import { createVNode, Fragment } from '../../src/vnode'
import { compile, render as domRender } from 'vue'
Expand Down Expand Up @@ -432,4 +434,42 @@ describe('renderer: teleport', () => {
`"<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)
})
})
22 changes: 10 additions & 12 deletions packages/runtime-core/src/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2096,7 +2096,16 @@ function baseCreateRenderer(
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 &&
// #1153: fast path should not be taken for non-stable (v-for) fragments
(type !== Fragment ||
Expand All @@ -2119,17 +2128,6 @@ function baseCreateRenderer(
unmountChildren(children as VNode[], parentComponent, parentSuspense)
}

if (shapeFlag & ShapeFlags.TELEPORT) {
;(vnode.type as typeof TeleportImpl).remove(
vnode,
parentComponent,
parentSuspense,
optimized,
internals,
doRemove
)
}

if (doRemove) {
remove(vnode)
}
Expand Down

0 comments on commit 3736496

Please sign in to comment.