Browse Source

fix(core): avoid mutating original children when cloning vnode

The on-demand clone strategy introduced in 956756b mutates the owner
array of the cloned vnode. This causes the newly cloned vnode to be
destroyed when the parent node is destroyed. This is fixed by cloning
the children array when cloning a vnode.

fix #7975
dev
Evan You 6 years ago
parent
commit
097f6229df
  1. 5
      src/core/vdom/vnode.js
  2. 54
      test/unit/features/component/component-slot.spec.js

5
src/core/vdom/vnode.js

@ -90,7 +90,10 @@ export function cloneVNode (vnode: VNode): VNode {
const cloned = new VNode(
vnode.tag,
vnode.data,
vnode.children,
// #7975
// clone children array to avoid mutating original in case of cloning
// a child.
vnode.children && vnode.children.slice(),
vnode.text,
vnode.elm,
vnode.context,

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

@ -886,4 +886,58 @@ describe('Component slot', () => {
expect(vm.$el.textContent).toBe('foo')
}).then(done)
})
// #7975
it('should update named slot correctly when its position in the tree changed', done => {
const ChildComponent = {
template: '<b>{{ message }}</b>',
props: ['message']
}
let parentVm
const ParentComponent = {
template: `
<div>
<span v-if="alter">
<span><slot name="foo" /></span>
</span>
<span v-else>
<slot name="foo" />
</span>
</div>
`,
data () {
return {
alter: true
}
},
mounted () {
parentVm = this
}
}
const vm = new Vue({
template: `
<parent-component>
<span slot="foo">
<child-component :message="message" />
</span>
</parent-component>
`,
components: {
ChildComponent,
ParentComponent
},
data () {
return {
message: 1
}
}
}).$mount()
expect(vm.$el.firstChild.innerHTML).toBe('<span><span><b>1</b></span></span>')
parentVm.alter = false
waitForUpdate(() => {
vm.message = 2
}).then(() => {
expect(vm.$el.firstChild.innerHTML).toBe('<span><b>2</b></span>')
}).then(done)
})
})

Loading…
Cancel
Save