fix(teleport): proper children traversal when teleport is block root

fix #2324
This commit is contained in:
Evan You
2020-10-10 15:40:31 -04:00
parent 9bb14149b0
commit 2ae3b26679
2 changed files with 39 additions and 44 deletions

View File

@@ -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()