Skip to content

Commit dffeb1d

Browse files
committed
fix HOC root node replace updates
1 parent e0c77dd commit dffeb1d

File tree

3 files changed

+53
-9
lines changed

3 files changed

+53
-9
lines changed

src/core/instance/lifecycle.js

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -85,15 +85,9 @@ export function lifecycleMixin (Vue: Class<Component>) {
8585
if (vm.$el) {
8686
vm.$el.__vue__ = vm
8787
}
88-
// update parent vnode element after patch
89-
const parentNode = vm.$vnode
90-
if (parentNode) {
91-
parentNode.elm = vm.$el
92-
// update parent $el if the parent is HOC
93-
// this is necessary because child is updated after parent
94-
if (vm.$parent && parentNode === vm.$parent._vnode) {
95-
vm.$parent.$el = vm.$el
96-
}
88+
// if parent is an HOC, update its $el as well
89+
if (vm.$vnode && vm.$parent && vm.$vnode === vm.$parent._vnode) {
90+
vm.$parent.$el = vm.$el
9791
}
9892
if (vm._isMounted) {
9993
callHook(vm, 'updated')

src/core/vdom/patch.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ export function createPatchFunction (backend) {
8383
// component also has set the placeholder vnode's elm.
8484
// in that case we can just return the element and be done.
8585
if (isDef(i = vnode.child)) {
86+
vnode.elm = vnode.child.$el
8687
invokeCreateHooks(vnode, insertedVnodeQueue)
8788
setScope(vnode)
8889
return vnode.elm
@@ -415,6 +416,15 @@ export function createPatchFunction (backend) {
415416

416417
createElm(vnode, insertedVnodeQueue)
417418

419+
// component root element replaced.
420+
// update parent placeholder node element.
421+
if (vnode.parent) {
422+
vnode.parent.elm = vnode.elm
423+
for (let i = 0; i < cbs.create.length; ++i) {
424+
cbs.create[i](emptyNode, vnode.parent)
425+
}
426+
}
427+
418428
if (parent !== null) {
419429
nodeOps.insertBefore(parent, vnode.elm, nodeOps.nextSibling(elm))
420430
removeVnodes(parent, [oldVnode], 0, 0)

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

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,4 +236,44 @@ describe('Component', () => {
236236
})
237237
}).not.toThrow()
238238
})
239+
240+
it('properly update replaced higher-order component root node', done => {
241+
const vm = new Vue({
242+
data: {
243+
color: 'red'
244+
},
245+
template: '<test id="foo" :class="color"></test>',
246+
components: {
247+
test: {
248+
data () {
249+
return { tag: 'div' }
250+
},
251+
render (h) {
252+
return h(this.tag, { class: 'test' }, 'hi')
253+
}
254+
}
255+
}
256+
}).$mount()
257+
258+
expect(vm.$el.tagName).toBe('DIV')
259+
expect(vm.$el.id).toBe('foo')
260+
expect(vm.$el.className).toBe('test red')
261+
262+
vm.color = 'green'
263+
waitForUpdate(() => {
264+
expect(vm.$el.tagName).toBe('DIV')
265+
expect(vm.$el.id).toBe('foo')
266+
expect(vm.$el.className).toBe('test green')
267+
vm.$children[0].tag = 'p'
268+
}).then(() => {
269+
expect(vm.$el.tagName).toBe('P')
270+
expect(vm.$el.id).toBe('foo')
271+
expect(vm.$el.className).toBe('test green')
272+
vm.color = 'red'
273+
}).then(() => {
274+
expect(vm.$el.tagName).toBe('P')
275+
expect(vm.$el.id).toBe('foo')
276+
expect(vm.$el.className).toBe('test red')
277+
}).then(done)
278+
})
239279
})

0 commit comments

Comments
 (0)