Skip to content

Commit

Permalink
fix(vdom): avoid diff de-opt when both head/tail are different
Browse files Browse the repository at this point in the history
fix #6502
  • Loading branch information
yyx990803 committed Sep 4, 2017
1 parent f76d16e commit 230c6ae
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 4 deletions.
11 changes: 10 additions & 1 deletion src/core/vdom/patch.js
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,9 @@ export function createPatchFunction (backend) {
newStartVnode = newCh[++newStartIdx]
} else {
if (isUndef(oldKeyToIdx)) oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx)
idxInOld = isDef(newStartVnode.key) ? oldKeyToIdx[newStartVnode.key] : null
idxInOld = isDef(newStartVnode.key)
? oldKeyToIdx[newStartVnode.key]
: findIdxInOld(newStartVnode, oldCh, oldStartIdx, oldEndIdx)
if (isUndef(idxInOld)) { // New element
createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm)
newStartVnode = newCh[++newStartIdx]
Expand Down Expand Up @@ -435,6 +437,13 @@ export function createPatchFunction (backend) {
}
}

function findIdxInOld (node, oldCh, start, end) {
for (let i = start; i < end; i++) {
const c = oldCh[i]
if (isDef(c) && sameVnode(node, c)) return i
}
}

function patchVnode (oldVnode, vnode, insertedVnodeQueue, removeOnly) {
if (oldVnode === vnode) {
return
Expand Down
27 changes: 24 additions & 3 deletions test/unit/modules/vdom/patch/children.spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { patch } from 'web/runtime/patch'
import VNode from 'core/vdom/vnode'
import VNode, { createEmptyVNode } from 'core/vdom/vnode'

function prop (name) {
return obj => { return obj[name] }
Expand Down Expand Up @@ -445,7 +445,7 @@ describe('vdom patch: children', () => {
expect(child2.className).toBe('')
})

it('should handle static vnodes properly', function () {
it('should handle static vnodes properly', () => {
function makeNode (text) {
return new VNode('div', undefined, [
new VNode(undefined, undefined, undefined, text)
Expand All @@ -466,7 +466,7 @@ describe('vdom patch: children', () => {
expect(elm.textContent).toBe('ABC')
})

it('should handle static vnodes inside ', function () {
it('should handle static vnodes inside ', () => {
function makeNode (text) {
return new VNode('div', undefined, [
new VNode(undefined, undefined, undefined, text)
Expand All @@ -486,4 +486,25 @@ describe('vdom patch: children', () => {
elm = patch(vnode2, vnode3)
expect(elm.textContent).toBe('ABC')
})

// #6502
it('should not de-opt when both head and tail are changed', () => {
const vnode1 = new VNode('div', {}, [
createEmptyVNode(),
new VNode('div'),
createEmptyVNode()
])
const vnode2 = new VNode('div', {}, [
new VNode('p'),
new VNode('div'),
new VNode('p')
])
let root = patch(null, vnode1)
const original = root.childNodes[1]

root = patch(vnode1, vnode2)
const postPatch = root.childNodes[1]

expect(postPatch).toBe(original)
})
})

0 comments on commit 230c6ae

Please sign in to comment.