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,
|
MoveType,
|
||||||
RendererElement,
|
RendererElement,
|
||||||
RendererNode,
|
RendererNode,
|
||||||
RendererOptions
|
RendererOptions,
|
||||||
|
traverseStaticChildren
|
||||||
} from '../renderer'
|
} from '../renderer'
|
||||||
import { VNode, VNodeArrayChildren, VNodeProps } from '../vnode'
|
import { VNode, VNodeArrayChildren, VNodeProps } from '../vnode'
|
||||||
import { isString, ShapeFlags } from '@vue/shared'
|
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
|
// 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
|
// in the teleport inherit previous DOM references so that they can
|
||||||
// be moved in future patches.
|
// be moved in future patches.
|
||||||
if (n2.shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
traverseStaticChildren(n1, n2, true)
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (!optimized) {
|
} else if (!optimized) {
|
||||||
patchChildren(
|
patchChildren(
|
||||||
n1,
|
n1,
|
||||||
|
@ -2190,39 +2190,6 @@ function baseCreateRenderer(
|
|||||||
return hostNextSibling((vnode.anchor || vnode.el)!)
|
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) => {
|
const render: RootRenderFunction = (vnode, container) => {
|
||||||
if (vnode == null) {
|
if (vnode == null) {
|
||||||
if (container._vnode) {
|
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
|
// https://en.wikipedia.org/wiki/Longest_increasing_subsequence
|
||||||
function getSequence(arr: number[]): number[] {
|
function getSequence(arr: number[]): number[] {
|
||||||
const p = arr.slice()
|
const p = arr.slice()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user