fix(runtime-core): use correct container for moving Teleport content (#1703)

This commit is contained in:
underfin 2020-07-28 23:23:39 +08:00 committed by GitHub
parent fbf865d9d4
commit 04a4ebaaeb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 2 deletions

View File

@ -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>"`
)
})
}) })

View File

@ -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,

View File

@ -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.