From 285e3d7c522c15edfa23a9bcd962af6d745522b7 Mon Sep 17 00:00:00 2001 From: Jesse Date: Mon, 16 Jul 2018 21:05:30 +0800 Subject: [PATCH] fix(patch): static tree should ba as same vnode(#8021) --- src/core/vdom/patch.js | 15 ++++++--- test/unit/features/directives/once.spec.js | 36 ++++++++++++++++++++++ 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/src/core/vdom/patch.js b/src/core/vdom/patch.js index fb28d8cd341..ec70b9f685a 100644 --- a/src/core/vdom/patch.js +++ b/src/core/vdom/patch.js @@ -44,7 +44,7 @@ function sameVnode (a, b) { isTrue(a.isAsyncPlaceholder) && a.asyncFactory === b.asyncFactory && isUndef(b.asyncFactory.error) - ) + ) || sameStaticVnode(a, b) ) ) } @@ -57,6 +57,12 @@ function sameInputType (a, b) { return typeA === typeB || isTextInputType(typeA) && isTextInputType(typeB) } +function sameStaticVnode (a, b) { + return isTrue(a.isStatic) && + isTrue(b.isStatic) && + (isTrue(b.isCloned) || isTrue(b.isOnce)) +} + function createKeyToOldIdx (children, beginIdx, endIdx) { let i, key const map = {} @@ -518,10 +524,9 @@ export function createPatchFunction (backend) { // note we only do this if the vnode is cloned - // if the new node is not cloned it means the render functions have been // reset by the hot-reload-api and we need to do a proper re-render. - if (isTrue(vnode.isStatic) && - isTrue(oldVnode.isStatic) && - vnode.key === oldVnode.key && - (isTrue(vnode.isCloned) || isTrue(vnode.isOnce)) + if ( + sameStaticVnode(oldVnode, vnode) && + vnode.key === oldVnode.key ) { vnode.componentInstance = oldVnode.componentInstance return diff --git a/test/unit/features/directives/once.spec.js b/test/unit/features/directives/once.spec.js index eca8be0a3ef..90fb7e85be9 100644 --- a/test/unit/features/directives/once.spec.js +++ b/test/unit/features/directives/once.spec.js @@ -176,6 +176,42 @@ describe('Directive v-once', () => { }).then(done) }) + it('should work inside v-for in component', done => { + const vm = new Vue({ + data: { + comp: 'comp1', + list: [ + { id: 0 } + ] + }, + components: { + comp1: { + template: 'comp1' + }, + comp2: { + template: 'comp2' + } + }, + template: ` +
+
+ +
+
+ ` + }).$mount() + + expect(vm.$el.textContent).toBe('comp1') + + vm.comp = 'comp2' + waitForUpdate(() => { + expect(vm.$el.textContent).toBe('comp1') + vm.list.push({ id: 1 }) + }).then(() => { + expect(vm.$el.textContent).toBe('comp1comp2') + }).then(done) + }) + it('should work inside v-for with v-if', done => { const vm = new Vue({ data: {