Skip to content

Commit 1cf02ef

Browse files
committed
fix: also clone component slot children during deepClone
fix #6891, fix #6915
1 parent cfd73c2 commit 1cf02ef

File tree

3 files changed

+22
-9
lines changed

3 files changed

+22
-9
lines changed

src/core/vdom/patch.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -673,9 +673,12 @@ export function createPatchFunction (backend) {
673673
// create an empty node and replace it
674674
oldVnode = emptyNodeAt(oldVnode)
675675
}
676+
676677
// replacing existing element
677678
const oldElm = oldVnode.elm
678679
const parentElm = nodeOps.parentNode(oldElm)
680+
681+
// create new node
679682
createElm(
680683
vnode,
681684
insertedVnodeQueue,
@@ -686,9 +689,8 @@ export function createPatchFunction (backend) {
686689
nodeOps.nextSibling(oldElm)
687690
)
688691

692+
// update parent placeholder node element, recursively
689693
if (isDef(vnode.parent)) {
690-
// component root element replaced.
691-
// update parent placeholder node element, recursively
692694
let ancestor = vnode.parent
693695
const patchable = isPatchable(vnode)
694696
while (ancestor) {
@@ -717,6 +719,7 @@ export function createPatchFunction (backend) {
717719
}
718720
}
719721

722+
// destroy old node
720723
if (isDef(parentElm)) {
721724
removeVnodes(parentElm, [oldVnode], 0, 0)
722725
} else if (isDef(oldVnode.tag)) {

src/core/vdom/vnode.js

+9-3
Original file line numberDiff line numberDiff line change
@@ -86,23 +86,29 @@ export function createTextVNode (val: string | number) {
8686
// multiple renders, cloning them avoids errors when DOM manipulations rely
8787
// on their elm reference.
8888
export function cloneVNode (vnode: VNode, deep?: boolean): VNode {
89+
const componentOptions = vnode.componentOptions
8990
const cloned = new VNode(
9091
vnode.tag,
9192
vnode.data,
9293
vnode.children,
9394
vnode.text,
9495
vnode.elm,
9596
vnode.context,
96-
vnode.componentOptions,
97+
componentOptions,
9798
vnode.asyncFactory
9899
)
99100
cloned.ns = vnode.ns
100101
cloned.isStatic = vnode.isStatic
101102
cloned.key = vnode.key
102103
cloned.isComment = vnode.isComment
103104
cloned.isCloned = true
104-
if (deep && vnode.children) {
105-
cloned.children = cloneVNodes(vnode.children)
105+
if (deep) {
106+
if (vnode.children) {
107+
cloned.children = cloneVNodes(vnode.children, true)
108+
}
109+
if (componentOptions && componentOptions.children) {
110+
componentOptions.children = cloneVNodes(componentOptions.children, true)
111+
}
106112
}
107113
return cloned
108114
}

test/unit/features/component/component-slot.spec.js

+8-4
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,7 @@ describe('Component slot', () => {
686686
expect(vm.$el.innerHTML).toBe('<div>default<span>foo</span></div>')
687687
})
688688

689+
// #6372, #6915
689690
it('should handle nested components in slots properly', done => {
690691
const TestComponent = {
691692
template: `
@@ -706,7 +707,10 @@ describe('Component slot', () => {
706707
<test-component ref="test">
707708
<div>
708709
<foo/>
709-
</div><bar/>
710+
</div>
711+
<bar>
712+
<foo/>
713+
</bar>
710714
</test-component>
711715
</div>
712716
`,
@@ -716,16 +720,16 @@ describe('Component slot', () => {
716720
template: `<div>foo</div>`
717721
},
718722
bar: {
719-
template: `<div>bar</div>`
723+
template: `<div>bar<slot/></div>`
720724
}
721725
}
722726
}).$mount()
723727

724-
expect(vm.$el.innerHTML).toBe(`<b><div><div>foo</div></div><div>bar</div></b>`)
728+
expect(vm.$el.innerHTML).toBe(`<b><div><div>foo</div></div> <div>bar<div>foo</div></div></b>`)
725729

726730
vm.$refs.test.toggleEl = false
727731
waitForUpdate(() => {
728-
expect(vm.$el.innerHTML).toBe(`<i><div><div>foo</div></div><div>bar</div></i>`)
732+
expect(vm.$el.innerHTML).toBe(`<i><div><div>foo</div></div> <div>bar<div>foo</div></div></i>`)
729733
}).then(done)
730734
})
731735

0 commit comments

Comments
 (0)