more proper fix for same-key different-tag children handling

This commit is contained in:
Evan You 2016-06-02 15:21:22 -04:00
parent d237aabc26
commit d3547f323c
2 changed files with 14 additions and 25 deletions

View File

@ -105,13 +105,13 @@ function prepatch (
oldVnode: MountedComponentVNode, oldVnode: MountedComponentVNode,
vnode: MountedComponentVNode vnode: MountedComponentVNode
) { ) {
const { listeners, propsData, children } = vnode.componentOptions const options = vnode.componentOptions
vnode.child = oldVnode.child vnode.child = oldVnode.child
vnode.child._updateFromParent( vnode.child._updateFromParent(
propsData, // updated props options.propsData, // updated props
listeners, // updated listeners options.listeners, // updated listeners
vnode, // new parent vnode vnode, // new parent vnode
children // new children options.children // new children
) )
} }

View File

@ -228,20 +228,16 @@ export function createPatchFunction (backend) {
'Make sure each v-for item has a unique key.' 'Make sure each v-for item has a unique key.'
) )
} }
patchVnode(elmToMove, newStartVnode, insertedVnodeQueue) if (elmToMove.tag !== newStartVnode.tag) {
// possible edge case: if elmToMove and newStartVnode are not the // same key but different element. treat as new element
// same vnode (e.g. same key, different tag), the elmToMove is replaced nodeOps.insertBefore(parentElm, createElm(newStartVnode, insertedVnodeQueue), oldStartVnode.elm)
// by the newStartVnode. If elmToMove happens to be the oldStartVnode, newStartVnode = newCh[++newStartIdx]
// the oldStartVnode will be holding on to an element that has been } else {
// removed from the DOM. This causes later moving operations to patchVnode(elmToMove, newStartVnode, insertedVnodeQueue)
// fail. This can be fixed by replacing the oldStartVnode with the oldCh[idxInOld] = undefined
// newStartVnode. nodeOps.insertBefore(parentElm, newStartVnode.elm, oldStartVnode.elm)
if (elmToMove === oldStartVnode) { newStartVnode = newCh[++newStartIdx]
oldStartVnode = newStartVnode
} }
oldCh[idxInOld] = undefined
nodeOps.insertBefore(parentElm, newStartVnode.elm, oldStartVnode.elm)
newStartVnode = newCh[++newStartIdx]
} }
} }
} }
@ -258,17 +254,10 @@ export function createPatchFunction (backend) {
if (isDef(i = vnode.data) && isDef(hook = i.hook) && isDef(i = hook.prepatch)) { if (isDef(i = vnode.data) && isDef(hook = i.hook) && isDef(i = hook.prepatch)) {
i(oldVnode, vnode) i(oldVnode, vnode)
} }
let elm = vnode.elm = oldVnode.elm const elm = vnode.elm = oldVnode.elm
const oldCh = oldVnode.children const oldCh = oldVnode.children
const ch = vnode.children const ch = vnode.children
if (oldVnode === vnode) return if (oldVnode === vnode) return
if (!sameVnode(oldVnode, vnode)) {
const parentElm = nodeOps.parentNode(oldVnode.elm)
elm = createElm(vnode, insertedVnodeQueue)
nodeOps.insertBefore(parentElm, elm, oldVnode.elm)
removeVnodes(parentElm, [oldVnode], 0, 0)
return
}
if (isDef(vnode.data)) { if (isDef(vnode.data)) {
for (i = 0; i < cbs.update.length; ++i) cbs.update[i](oldVnode, vnode) for (i = 0; i < cbs.update.length; ++i) cbs.update[i](oldVnode, vnode)
if (isDef(hook) && isDef(i = hook.update)) i(oldVnode, vnode) if (isDef(hook) && isDef(i = hook.update)) i(oldVnode, vnode)