diff --git a/src/core/vdom/patch.js b/src/core/vdom/patch.js index 4fcb9157090..dcdaf239eef 100644 --- a/src/core/vdom/patch.js +++ b/src/core/vdom/patch.js @@ -660,14 +660,18 @@ export function createPatchFunction (backend) { // component root element replaced. // update parent placeholder node element, recursively let ancestor = vnode.parent + const patchable = isPatchable(vnode) while (ancestor) { + for (let i = 0; i < cbs.destroy.length; ++i) { + cbs.destroy[i](ancestor) + } ancestor.elm = vnode.elm - ancestor = ancestor.parent - } - if (isPatchable(vnode)) { - for (let i = 0; i < cbs.create.length; ++i) { - cbs.create[i](emptyNode, vnode.parent) + if (patchable) { + for (let i = 0; i < cbs.create.length; ++i) { + cbs.create[i](emptyNode, ancestor) + } } + ancestor = ancestor.parent } } diff --git a/test/unit/modules/vdom/patch/edge-cases.spec.js b/test/unit/modules/vdom/patch/edge-cases.spec.js index f80a741f55a..05135246b36 100644 --- a/test/unit/modules/vdom/patch/edge-cases.spec.js +++ b/test/unit/modules/vdom/patch/edge-cases.spec.js @@ -161,4 +161,32 @@ describe('vdom patch: edge cases', () => { expect(vm.$el.children[0].type).toBe('password') }).then(done) }) + + it('should properly patch nested HOC when root element is replaced', done => { + const vm = new Vue({ + template: ``, + components: { + foo: { + template: ``, + components: { + bar: { + template: `
`, + data () { + return { ok: true } + } + } + } + } + } + }).$mount() + + expect(vm.$refs.foo.$refs.bar.$el.tagName).toBe('DIV') + expect(vm.$refs.foo.$refs.bar.$el.className).toBe(`hello`) + + vm.$refs.foo.$refs.bar.ok = false + waitForUpdate(() => { + expect(vm.$refs.foo.$refs.bar.$el.tagName).toBe('SPAN') + expect(vm.$refs.foo.$refs.bar.$el.className).toBe(`hello`) + }).then(done) + }) })