Skip to content

Commit 74f8b98

Browse files
committed
handle static vnodes properly during patch (fix #3325)
1 parent e84a1a4 commit 74f8b98

File tree

4 files changed

+38
-6
lines changed

4 files changed

+38
-6
lines changed

src/core/instance/render.js

+7-4
Original file line numberDiff line numberDiff line change
@@ -103,13 +103,16 @@ export function renderMixin (Vue: Class<Component>) {
103103
// number conversion
104104
Vue.prototype._n = toNumber
105105

106-
//
106+
// render static tree by index
107107
Vue.prototype._m = function renderStatic (index?: number): Object | void {
108-
return this._staticTrees[index] || (
109-
this._staticTrees[index] = this.$options.staticRenderFns[index].call(
108+
let tree = this._staticTrees[index]
109+
if (!tree) {
110+
tree = this._staticTrees[index] = this.$options.staticRenderFns[index].call(
110111
this._renderProxy
111112
)
112-
)
113+
tree.isStatic = true
114+
}
115+
return tree
113116
}
114117

115118
// filter resolution helper

src/core/vdom/patch.js

+9-2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ function isDef (s) {
2424
}
2525

2626
function sameVnode (vnode1, vnode2) {
27+
if (vnode1.isStatic || vnode2.isStatic) {
28+
return vnode1 === vnode2
29+
}
2730
return (
2831
vnode1.key === vnode2.key &&
2932
vnode1.tag === vnode2.tag &&
@@ -259,8 +262,12 @@ export function createPatchFunction (backend) {
259262
newStartVnode = newCh[++newStartIdx]
260263
} else {
261264
if (isUndef(oldKeyToIdx)) oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx)
262-
idxInOld = oldKeyToIdx[newStartVnode.key]
263-
if (isUndef(idxInOld)) { // New element
265+
idxInOld = isDef(newStartVnode.key)
266+
? oldKeyToIdx[newStartVnode.key]
267+
: newStartVnode.isStatic
268+
? oldCh.indexOf(newStartVnode)
269+
: null
270+
if (isUndef(idxInOld) || idxInOld === -1) { // New element
264271
nodeOps.insertBefore(parentElm, createElm(newStartVnode, insertedVnodeQueue), oldStartVnode.elm)
265272
newStartVnode = newCh[++newStartIdx]
266273
} else {

src/core/vdom/vnode.js

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export default class VNode {
1414
child: Component | void;
1515
parent: VNode | void;
1616
raw: ?boolean;
17+
isStatic: ?boolean;
1718

1819
constructor (
1920
tag?: string,
@@ -39,6 +40,7 @@ export default class VNode {
3940
this.child = undefined
4041
this.parent = undefined
4142
this.raw = false
43+
this.isStatic = false
4244
// apply construct hook.
4345
// this is applied during render, before patch happens.
4446
// unlike other hooks, this is applied on both client and server.

test/unit/modules/vdom/patch/children.spec.js

+20
Original file line numberDiff line numberDiff line change
@@ -466,4 +466,24 @@ describe('children', () => {
466466
expect(child1).not.toBe(child2)
467467
expect(child2.className).toBe('')
468468
})
469+
470+
it('should handle static vnodes properly', function () {
471+
function makeNode (text) {
472+
return new VNode('div', undefined, [
473+
new VNode(undefined, undefined, undefined, text)
474+
])
475+
}
476+
const b = makeNode('B')
477+
b.isStatic = true
478+
const vnode1 = new VNode('div', {}, [makeNode('A'), b, makeNode('C')])
479+
const vnode2 = new VNode('div', {}, [b])
480+
const vnode3 = new VNode('div', {}, [makeNode('A'), b, makeNode('C')])
481+
482+
let elm = patch(vnode0, vnode1)
483+
expect(elm.textContent).toBe('ABC')
484+
elm = patch(vnode1, vnode2)
485+
expect(elm.textContent).toBe('B')
486+
elm = patch(vnode2, vnode3)
487+
expect(elm.textContent).toBe('ABC')
488+
})
469489
})

0 commit comments

Comments
 (0)