Browse Source

handle static vnodes properly during patch (fix #3325)

dev
Evan You 8 years ago
parent
commit
74f8b98509
  1. 11
      src/core/instance/render.js
  2. 11
      src/core/vdom/patch.js
  3. 2
      src/core/vdom/vnode.js
  4. 20
      test/unit/modules/vdom/patch/children.spec.js

11
src/core/instance/render.js

@ -103,13 +103,16 @@ export function renderMixin (Vue: Class<Component>) {
// number conversion
Vue.prototype._n = toNumber
//
// render static tree by index
Vue.prototype._m = function renderStatic (index?: number): Object | void {
return this._staticTrees[index] || (
this._staticTrees[index] = this.$options.staticRenderFns[index].call(
let tree = this._staticTrees[index]
if (!tree) {
tree = this._staticTrees[index] = this.$options.staticRenderFns[index].call(
this._renderProxy
)
)
tree.isStatic = true
}
return tree
}
// filter resolution helper

11
src/core/vdom/patch.js

@ -24,6 +24,9 @@ function isDef (s) {
}
function sameVnode (vnode1, vnode2) {
if (vnode1.isStatic || vnode2.isStatic) {
return vnode1 === vnode2
}
return (
vnode1.key === vnode2.key &&
vnode1.tag === vnode2.tag &&
@ -259,8 +262,12 @@ export function createPatchFunction (backend) {
newStartVnode = newCh[++newStartIdx]
} else {
if (isUndef(oldKeyToIdx)) oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx)
idxInOld = oldKeyToIdx[newStartVnode.key]
if (isUndef(idxInOld)) { // New element
idxInOld = isDef(newStartVnode.key)
? oldKeyToIdx[newStartVnode.key]
: newStartVnode.isStatic
? oldCh.indexOf(newStartVnode)
: null
if (isUndef(idxInOld) || idxInOld === -1) { // New element
nodeOps.insertBefore(parentElm, createElm(newStartVnode, insertedVnodeQueue), oldStartVnode.elm)
newStartVnode = newCh[++newStartIdx]
} else {

2
src/core/vdom/vnode.js

@ -14,6 +14,7 @@ export default class VNode {
child: Component | void;
parent: VNode | void;
raw: ?boolean;
isStatic: ?boolean;
constructor (
tag?: string,
@ -39,6 +40,7 @@ export default class VNode {
this.child = undefined
this.parent = undefined
this.raw = false
this.isStatic = false
// apply construct hook.
// this is applied during render, before patch happens.
// unlike other hooks, this is applied on both client and server.

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

@ -466,4 +466,24 @@ describe('children', () => {
expect(child1).not.toBe(child2)
expect(child2.className).toBe('')
})
it('should handle static vnodes properly', function () {
function makeNode (text) {
return new VNode('div', undefined, [
new VNode(undefined, undefined, undefined, text)
])
}
const b = makeNode('B')
b.isStatic = true
const vnode1 = new VNode('div', {}, [makeNode('A'), b, makeNode('C')])
const vnode2 = new VNode('div', {}, [b])
const vnode3 = new VNode('div', {}, [makeNode('A'), b, makeNode('C')])
let elm = patch(vnode0, vnode1)
expect(elm.textContent).toBe('ABC')
elm = patch(vnode1, vnode2)
expect(elm.textContent).toBe('B')
elm = patch(vnode2, vnode3)
expect(elm.textContent).toBe('ABC')
})
})

Loading…
Cancel
Save