Skip to content

Commit 8c907d4

Browse files
yyx990803hefeng
authored and
hefeng
committed
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 vuejs#7975
1 parent 10a31d9 commit 8c907d4

File tree

2 files changed

+58
-1
lines changed

2 files changed

+58
-1
lines changed

src/core/vdom/vnode.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,10 @@ export function cloneVNode (vnode: VNode): VNode {
9090
const cloned = new VNode(
9191
vnode.tag,
9292
vnode.data,
93-
vnode.children,
93+
// #7975
94+
// clone children array to avoid mutating original in case of cloning
95+
// a child.
96+
vnode.children && vnode.children.slice(),
9497
vnode.text,
9598
vnode.elm,
9699
vnode.context,

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

+54
Original file line numberDiff line numberDiff line change
@@ -886,4 +886,58 @@ describe('Component slot', () => {
886886
expect(vm.$el.textContent).toBe('foo')
887887
}).then(done)
888888
})
889+
890+
// #7975
891+
it('should update named slot correctly when its position in the tree changed', done => {
892+
const ChildComponent = {
893+
template: '<b>{{ message }}</b>',
894+
props: ['message']
895+
}
896+
let parentVm
897+
const ParentComponent = {
898+
template: `
899+
<div>
900+
<span v-if="alter">
901+
<span><slot name="foo" /></span>
902+
</span>
903+
<span v-else>
904+
<slot name="foo" />
905+
</span>
906+
</div>
907+
`,
908+
data () {
909+
return {
910+
alter: true
911+
}
912+
},
913+
mounted () {
914+
parentVm = this
915+
}
916+
}
917+
const vm = new Vue({
918+
template: `
919+
<parent-component>
920+
<span slot="foo">
921+
<child-component :message="message" />
922+
</span>
923+
</parent-component>
924+
`,
925+
components: {
926+
ChildComponent,
927+
ParentComponent
928+
},
929+
data () {
930+
return {
931+
message: 1
932+
}
933+
}
934+
}).$mount()
935+
expect(vm.$el.firstChild.innerHTML).toBe('<span><span><b>1</b></span></span>')
936+
parentVm.alter = false
937+
waitForUpdate(() => {
938+
vm.message = 2
939+
}).then(() => {
940+
expect(vm.$el.firstChild.innerHTML).toBe('<span><b>2</b></span>')
941+
}).then(done)
942+
})
889943
})

0 commit comments

Comments
 (0)