Skip to content

Commit

Permalink
fix: also clone component slot children during deepClone
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 authored and lovelope committed Feb 1, 2018
1 parent 707b2cc commit 5f85350
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 9 deletions.
7 changes: 5 additions & 2 deletions src/core/vdom/patch.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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) {
Expand Down Expand Up @@ -717,6 +719,7 @@ export function createPatchFunction (backend) {
}
}

// destroy old node
if (isDef(parentElm)) {
removeVnodes(parentElm, [oldVnode], 0, 0)
} else if (isDef(oldVnode.tag)) {
Expand Down
12 changes: 9 additions & 3 deletions src/core/vdom/vnode.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,23 +86,29 @@ 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,
vnode.children,
vnode.text,
vnode.elm,
vnode.context,
vnode.componentOptions,
componentOptions,
vnode.asyncFactory
)
cloned.ns = vnode.ns
cloned.isStatic = vnode.isStatic
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
}
Expand Down
12 changes: 8 additions & 4 deletions test/unit/features/component/component-slot.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,7 @@ describe('Component slot', () => {
expect(vm.$el.innerHTML).toBe('<div>default<span>foo</span></div>')
})

// #6372, #6915
it('should handle nested components in slots properly', done => {
const TestComponent = {
template: `
Expand All @@ -706,7 +707,10 @@ describe('Component slot', () => {
<test-component ref="test">
<div>
<foo/>
</div><bar/>
</div>
<bar>
<foo/>
</bar>
</test-component>
</div>
`,
Expand All @@ -716,16 +720,16 @@ describe('Component slot', () => {
template: `<div>foo</div>`
},
bar: {
template: `<div>bar</div>`
template: `<div>bar<slot/></div>`
}
}
}).$mount()

expect(vm.$el.innerHTML).toBe(`<b><div><div>foo</div></div><div>bar</div></b>`)
expect(vm.$el.innerHTML).toBe(`<b><div><div>foo</div></div> <div>bar<div>foo</div></div></b>`)

vm.$refs.test.toggleEl = false
waitForUpdate(() => {
expect(vm.$el.innerHTML).toBe(`<i><div><div>foo</div></div><div>bar</div></i>`)
expect(vm.$el.innerHTML).toBe(`<i><div><div>foo</div></div> <div>bar<div>foo</div></div></i>`)
}).then(done)
})

Expand Down

0 comments on commit 5f85350

Please sign in to comment.