|
|
@@ -10,7 +10,7 @@
|
|
|
* of making flow understand it is not worth it.
|
|
|
*/
|
|
|
|
|
|
-import VNode from './vnode'
|
|
|
+import VNode, { cloneVNode } from './vnode'
|
|
|
import config from '../config'
|
|
|
import { SSR_ATTR } from 'shared/constants'
|
|
|
import { registerRef } from './modules/ref'
|
|
|
@@ -121,7 +121,25 @@ export function createPatchFunction (backend) {
|
|
|
}
|
|
|
|
|
|
let creatingElmInVPre = 0
|
|
|
- function createElm (vnode, insertedVnodeQueue, parentElm, refElm, nested) {
|
|
|
+
|
|
|
+ function createElm (
|
|
|
+ vnode,
|
|
|
+ insertedVnodeQueue,
|
|
|
+ parentElm,
|
|
|
+ refElm,
|
|
|
+ nested,
|
|
|
+ ownerArray,
|
|
|
+ index
|
|
|
+ ) {
|
|
|
+ if (isDef(vnode.elm) && isDef(ownerArray)) {
|
|
|
+ // This vnode was used in a previous render!
|
|
|
+ // now it's used as a new node, overwriting its elm would cause
|
|
|
+ // potential patch errors down the road when it's used as an insertion
|
|
|
+ // reference node. Instead, we clone the node on-demand before creating
|
|
|
+ // associated DOM element for it.
|
|
|
+ vnode = ownerArray[index] = cloneVNode(vnode)
|
|
|
+ }
|
|
|
+
|
|
|
vnode.isRootInsert = !nested // for transition enter check
|
|
|
if (createComponent(vnode, insertedVnodeQueue, parentElm, refElm)) {
|
|
|
return
|
|
|
@@ -144,6 +162,7 @@ export function createPatchFunction (backend) {
|
|
|
)
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
vnode.elm = vnode.ns
|
|
|
? nodeOps.createElementNS(vnode.ns, tag)
|
|
|
: nodeOps.createElement(tag, vnode)
|
|
|
@@ -267,7 +286,7 @@ export function createPatchFunction (backend) {
|
|
|
checkDuplicateKeys(children)
|
|
|
}
|
|
|
for (let i = 0; i < children.length; ++i) {
|
|
|
- createElm(children[i], insertedVnodeQueue, vnode.elm, null, true)
|
|
|
+ createElm(children[i], insertedVnodeQueue, vnode.elm, null, true, children, i)
|
|
|
}
|
|
|
} else if (isPrimitive(vnode.text)) {
|
|
|
nodeOps.appendChild(vnode.elm, nodeOps.createTextNode(String(vnode.text)))
|
|
|
@@ -320,7 +339,7 @@ export function createPatchFunction (backend) {
|
|
|
|
|
|
function addVnodes (parentElm, refElm, vnodes, startIdx, endIdx, insertedVnodeQueue) {
|
|
|
for (; startIdx <= endIdx; ++startIdx) {
|
|
|
- createElm(vnodes[startIdx], insertedVnodeQueue, parentElm, refElm)
|
|
|
+ createElm(vnodes[startIdx], insertedVnodeQueue, parentElm, refElm, false, vnodes, startIdx)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -430,7 +449,7 @@ export function createPatchFunction (backend) {
|
|
|
? oldKeyToIdx[newStartVnode.key]
|
|
|
: findIdxInOld(newStartVnode, oldCh, oldStartIdx, oldEndIdx)
|
|
|
if (isUndef(idxInOld)) { // New element
|
|
|
- createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm)
|
|
|
+ createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm, false, newCh, newStartIdx)
|
|
|
} else {
|
|
|
vnodeToMove = oldCh[idxInOld]
|
|
|
if (sameVnode(vnodeToMove, newStartVnode)) {
|
|
|
@@ -439,7 +458,7 @@ export function createPatchFunction (backend) {
|
|
|
canMove && nodeOps.insertBefore(parentElm, vnodeToMove.elm, oldStartVnode.elm)
|
|
|
} else {
|
|
|
// same key but different element. treat as new element
|
|
|
- createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm)
|
|
|
+ createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm, false, newCh, newStartIdx)
|
|
|
}
|
|
|
}
|
|
|
newStartVnode = newCh[++newStartIdx]
|