diff --git a/src/core/vdom/patch.js b/src/core/vdom/patch.js index f06a1feb079..1a764f20cf8 100644 --- a/src/core/vdom/patch.js +++ b/src/core/vdom/patch.js @@ -673,9 +673,12 @@ export function createPatchFunction (backend) { // create an empty node and replace it oldVnode = emptyNodeAt(oldVnode) } + // replacing existing element const oldElm = oldVnode.elm const parentElm = nodeOps.parentNode(oldElm) + + // create new node createElm( vnode, insertedVnodeQueue, @@ -686,9 +689,8 @@ export function createPatchFunction (backend) { nodeOps.nextSibling(oldElm) ) + // update parent placeholder node element, recursively if (isDef(vnode.parent)) { - // component root element replaced. - // update parent placeholder node element, recursively let ancestor = vnode.parent const patchable = isPatchable(vnode) while (ancestor) { @@ -717,6 +719,7 @@ export function createPatchFunction (backend) { } } + // destroy old node if (isDef(parentElm)) { removeVnodes(parentElm, [oldVnode], 0, 0) } else if (isDef(oldVnode.tag)) { diff --git a/src/core/vdom/vnode.js b/src/core/vdom/vnode.js index a34330de55b..33b5612fe6e 100644 --- a/src/core/vdom/vnode.js +++ b/src/core/vdom/vnode.js @@ -86,6 +86,7 @@ export function createTextVNode (val: string | number) { // multiple renders, cloning them avoids errors when DOM manipulations rely // on their elm reference. export function cloneVNode (vnode: VNode, deep?: boolean): VNode { + const componentOptions = vnode.componentOptions const cloned = new VNode( vnode.tag, vnode.data, @@ -93,7 +94,7 @@ export function cloneVNode (vnode: VNode, deep?: boolean): VNode { vnode.text, vnode.elm, vnode.context, - vnode.componentOptions, + componentOptions, vnode.asyncFactory ) cloned.ns = vnode.ns @@ -101,8 +102,13 @@ export function cloneVNode (vnode: VNode, deep?: boolean): VNode { cloned.key = vnode.key cloned.isComment = vnode.isComment cloned.isCloned = true - if (deep && vnode.children) { - cloned.children = cloneVNodes(vnode.children) + if (deep) { + if (vnode.children) { + cloned.children = cloneVNodes(vnode.children, true) + } + if (componentOptions && componentOptions.children) { + componentOptions.children = cloneVNodes(componentOptions.children, true) + } } return cloned } diff --git a/test/unit/features/component/component-slot.spec.js b/test/unit/features/component/component-slot.spec.js index 66e70dac17b..4ceadfc2153 100644 --- a/test/unit/features/component/component-slot.spec.js +++ b/test/unit/features/component/component-slot.spec.js @@ -686,6 +686,7 @@ describe('Component slot', () => { expect(vm.$el.innerHTML).toBe('
defaultfoo
') }) + // #6372, #6915 it('should handle nested components in slots properly', done => { const TestComponent = { template: ` @@ -706,7 +707,10 @@ describe('Component slot', () => {
-
+ + + +
`, @@ -716,16 +720,16 @@ describe('Component slot', () => { template: `
foo
` }, bar: { - template: `
bar
` + template: `
bar
` } } }).$mount() - expect(vm.$el.innerHTML).toBe(`
foo
bar
`) + expect(vm.$el.innerHTML).toBe(`
foo
bar
foo
`) vm.$refs.test.toggleEl = false waitForUpdate(() => { - expect(vm.$el.innerHTML).toBe(`
foo
bar
`) + expect(vm.$el.innerHTML).toBe(`
foo
bar
foo
`) }).then(done) })