fix(runtime-core): use correct container for moving Teleport
content (#1703)
This commit is contained in:
parent
fbf865d9d4
commit
04a4ebaaeb
@ -6,9 +6,11 @@ import {
|
|||||||
Teleport,
|
Teleport,
|
||||||
Text,
|
Text,
|
||||||
ref,
|
ref,
|
||||||
nextTick
|
nextTick,
|
||||||
|
markRaw
|
||||||
} from '@vue/runtime-test'
|
} from '@vue/runtime-test'
|
||||||
import { createVNode, Fragment } from '../../src/vnode'
|
import { createVNode, Fragment } from '../../src/vnode'
|
||||||
|
import { compile } from 'vue'
|
||||||
|
|
||||||
describe('renderer: teleport', () => {
|
describe('renderer: teleport', () => {
|
||||||
test('should work', () => {
|
test('should work', () => {
|
||||||
@ -299,4 +301,49 @@ describe('renderer: teleport', () => {
|
|||||||
)
|
)
|
||||||
expect(serializeInner(target)).toBe('')
|
expect(serializeInner(target)).toBe('')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('should work with block tree', async () => {
|
||||||
|
const target = nodeOps.createElement('div')
|
||||||
|
const root = nodeOps.createElement('div')
|
||||||
|
const disabled = ref(false)
|
||||||
|
|
||||||
|
const App = {
|
||||||
|
setup() {
|
||||||
|
return {
|
||||||
|
target: markRaw(target),
|
||||||
|
disabled
|
||||||
|
}
|
||||||
|
},
|
||||||
|
render: compile(`
|
||||||
|
<teleport :to="target" :disabled="disabled">
|
||||||
|
<div>teleported</div><span>{{ disabled }}</span>
|
||||||
|
</teleport>
|
||||||
|
<div>root</div>
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
render(h(App), root)
|
||||||
|
expect(serializeInner(root)).toMatchInlineSnapshot(
|
||||||
|
`"<!--teleport start--><!--teleport end--><div>root</div>"`
|
||||||
|
)
|
||||||
|
expect(serializeInner(target)).toMatchInlineSnapshot(
|
||||||
|
`"<div>teleported</div><span>false</span>"`
|
||||||
|
)
|
||||||
|
|
||||||
|
disabled.value = true
|
||||||
|
await nextTick()
|
||||||
|
expect(serializeInner(root)).toMatchInlineSnapshot(
|
||||||
|
`"<!--teleport start--><div>teleported</div><span>true</span><!--teleport end--><div>root</div>"`
|
||||||
|
)
|
||||||
|
expect(serializeInner(target)).toBe(``)
|
||||||
|
|
||||||
|
// toggle back
|
||||||
|
disabled.value = false
|
||||||
|
await nextTick()
|
||||||
|
expect(serializeInner(root)).toMatchInlineSnapshot(
|
||||||
|
`"<!--teleport start--><!--teleport end--><div>root</div>"`
|
||||||
|
)
|
||||||
|
expect(serializeInner(target)).toMatchInlineSnapshot(
|
||||||
|
`"<div>teleported</div><span>false</span>"`
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -139,6 +139,13 @@ export const TeleportImpl = {
|
|||||||
parentSuspense,
|
parentSuspense,
|
||||||
isSVG
|
isSVG
|
||||||
)
|
)
|
||||||
|
if (n2.patchFlag > 0 && n2.shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
||||||
|
const oldChildren = n1.children as VNode[]
|
||||||
|
const children = n2.children as VNode[]
|
||||||
|
for (let i = 0; i < children.length; i++) {
|
||||||
|
children[i].el = oldChildren[i].el
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (!optimized) {
|
} else if (!optimized) {
|
||||||
patchChildren(
|
patchChildren(
|
||||||
n1,
|
n1,
|
||||||
|
@ -960,7 +960,8 @@ function baseCreateRenderer(
|
|||||||
// which also requires the correct parent container
|
// which also requires the correct parent container
|
||||||
!isSameVNodeType(oldVNode, newVNode) ||
|
!isSameVNodeType(oldVNode, newVNode) ||
|
||||||
// - In the case of a component, it could contain anything.
|
// - In the case of a component, it could contain anything.
|
||||||
oldVNode.shapeFlag & ShapeFlags.COMPONENT
|
oldVNode.shapeFlag & ShapeFlags.COMPONENT ||
|
||||||
|
oldVNode.shapeFlag & ShapeFlags.TELEPORT
|
||||||
? hostParentNode(oldVNode.el!)!
|
? hostParentNode(oldVNode.el!)!
|
||||||
: // In other cases, the parent container is not actually used so we
|
: // In other cases, the parent container is not actually used so we
|
||||||
// just pass the block element here to avoid a DOM parentNode call.
|
// just pass the block element here to avoid a DOM parentNode call.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user