fix(teleport): proper children traversal when teleport is block root
fix #2324
This commit is contained in:
parent
9bb14149b0
commit
2ae3b26679
@ -5,7 +5,8 @@ import {
|
||||
MoveType,
|
||||
RendererElement,
|
||||
RendererNode,
|
||||
RendererOptions
|
||||
RendererOptions,
|
||||
traverseStaticChildren
|
||||
} from '../renderer'
|
||||
import { VNode, VNodeArrayChildren, VNodeProps } from '../vnode'
|
||||
import { isString, ShapeFlags } from '@vue/shared'
|
||||
@ -142,16 +143,7 @@ export const TeleportImpl = {
|
||||
// even in block tree mode we need to make sure all root-level nodes
|
||||
// in the teleport inherit previous DOM references so that they can
|
||||
// be moved in future patches.
|
||||
if (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++) {
|
||||
// only inherit for non-patched nodes (i.e. static ones)
|
||||
if (!children[i].el) {
|
||||
children[i].el = oldChildren[i].el
|
||||
}
|
||||
}
|
||||
}
|
||||
traverseStaticChildren(n1, n2, true)
|
||||
} else if (!optimized) {
|
||||
patchChildren(
|
||||
n1,
|
||||
|
@ -2190,39 +2190,6 @@ function baseCreateRenderer(
|
||||
return hostNextSibling((vnode.anchor || vnode.el)!)
|
||||
}
|
||||
|
||||
/**
|
||||
* #1156
|
||||
* When a component is HMR-enabled, we need to make sure that all static nodes
|
||||
* inside a block also inherit the DOM element from the previous tree so that
|
||||
* HMR updates (which are full updates) can retrieve the element for patching.
|
||||
*
|
||||
* #2080
|
||||
* Inside keyed `template` fragment static children, if a fragment is moved,
|
||||
* the children will always moved so that need inherit el form previous nodes
|
||||
* to ensure correct moved position.
|
||||
*/
|
||||
const traverseStaticChildren = (n1: VNode, n2: VNode, shallow = false) => {
|
||||
const ch1 = n1.children
|
||||
const ch2 = n2.children
|
||||
if (isArray(ch1) && isArray(ch2)) {
|
||||
for (let i = 0; i < ch1.length; i++) {
|
||||
// this is only called in the optimized path so array children are
|
||||
// guaranteed to be vnodes
|
||||
const c1 = ch1[i] as VNode
|
||||
const c2 = (ch2[i] = cloneIfMounted(ch2[i] as VNode))
|
||||
if (c2.shapeFlag & ShapeFlags.ELEMENT && !c2.dynamicChildren) {
|
||||
if (c2.patchFlag <= 0 || c2.patchFlag === PatchFlags.HYDRATE_EVENTS) {
|
||||
c2.el = c1.el
|
||||
}
|
||||
if (!shallow) traverseStaticChildren(c1, c2)
|
||||
}
|
||||
if (__DEV__ && c2.type === Comment) {
|
||||
c2.el = c1.el
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const render: RootRenderFunction = (vnode, container) => {
|
||||
if (vnode == null) {
|
||||
if (container._vnode) {
|
||||
@ -2276,6 +2243,42 @@ export function invokeVNodeHook(
|
||||
])
|
||||
}
|
||||
|
||||
/**
|
||||
* #1156
|
||||
* When a component is HMR-enabled, we need to make sure that all static nodes
|
||||
* inside a block also inherit the DOM element from the previous tree so that
|
||||
* HMR updates (which are full updates) can retrieve the element for patching.
|
||||
*
|
||||
* #2080
|
||||
* Inside keyed `template` fragment static children, if a fragment is moved,
|
||||
* the children will always moved so that need inherit el form previous nodes
|
||||
* to ensure correct moved position.
|
||||
*/
|
||||
export function traverseStaticChildren(n1: VNode, n2: VNode, shallow = false) {
|
||||
const ch1 = n1.children
|
||||
const ch2 = n2.children
|
||||
if (isArray(ch1) && isArray(ch2)) {
|
||||
for (let i = 0; i < ch1.length; i++) {
|
||||
// this is only called in the optimized path so array children are
|
||||
// guaranteed to be vnodes
|
||||
const c1 = ch1[i] as VNode
|
||||
let c2 = ch2[i] as VNode
|
||||
if (c2.shapeFlag & ShapeFlags.ELEMENT && !c2.dynamicChildren) {
|
||||
if (c2.patchFlag <= 0 || c2.patchFlag === PatchFlags.HYDRATE_EVENTS) {
|
||||
c2 = ch2[i] = cloneIfMounted(ch2[i] as VNode)
|
||||
c2.el = c1.el
|
||||
}
|
||||
if (!shallow) traverseStaticChildren(c1, c2)
|
||||
}
|
||||
// also inherit for comment nodes, but not placeholders (e.g. v-if which
|
||||
// would have received .el during block patch)
|
||||
if (__DEV__ && c2.type === Comment && !c2.el) {
|
||||
c2.el = c1.el
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// https://en.wikipedia.org/wiki/Longest_increasing_subsequence
|
||||
function getSequence(arr: number[]): number[] {
|
||||
const p = arr.slice()
|
||||
|
Loading…
x
Reference in New Issue
Block a user