Skip to content

Commit efb6035

Browse files
committed
fix patch modules error on empty component root
1 parent 397e64a commit efb6035

File tree

5 files changed

+48
-10
lines changed

5 files changed

+48
-10
lines changed

src/core/instance/lifecycle.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,15 +81,16 @@ export function lifecycleMixin (Vue: Class<Component>) {
8181
const prevEl = vm.$el
8282
const prevActiveInstance = activeInstance
8383
activeInstance = vm
84-
if (!vm._vnode) {
84+
const prevVnode = vm._vnode
85+
vm._vnode = vnode
86+
if (!prevVnode) {
8587
// Vue.prototype.__patch__ is injected in entry points
8688
// based on the rendering backend used.
8789
vm.$el = vm.__patch__(vm.$el, vnode, hydrating)
8890
} else {
89-
vm.$el = vm.__patch__(vm._vnode, vnode)
91+
vm.$el = vm.__patch__(prevVnode, vnode)
9092
}
9193
activeInstance = prevActiveInstance
92-
vm._vnode = vnode
9394
// update __vue__ reference
9495
if (prevEl) {
9596
prevEl.__vue__ = null

src/core/vdom/patch.js

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,13 @@ export function createPatchFunction (backend) {
129129
return vnode.elm
130130
}
131131

132+
function isPatchable (vnode) {
133+
while (vnode.child) {
134+
vnode = vnode.child._vnode
135+
}
136+
return isDef(vnode.tag)
137+
}
138+
132139
function invokeCreateHooks (vnode, insertedVnodeQueue) {
133140
for (let i = 0; i < cbs.create.length; ++i) {
134141
cbs.create[i](emptyNode, vnode)
@@ -145,9 +152,11 @@ export function createPatchFunction (backend) {
145152
insertedVnodeQueue.push.apply(insertedVnodeQueue, vnode.data.pendingInsert)
146153
}
147154
vnode.elm = vnode.child.$el
148-
invokeCreateHooks(vnode, insertedVnodeQueue)
149-
if (vnode.child._vnode.tag) {
155+
if (isPatchable(vnode)) {
156+
invokeCreateHooks(vnode, insertedVnodeQueue)
150157
setScope(vnode)
158+
} else {
159+
insertedVnodeQueue.push(vnode)
151160
}
152161
}
153162

@@ -322,7 +331,7 @@ export function createPatchFunction (backend) {
322331
const elm = vnode.elm = oldVnode.elm
323332
const oldCh = oldVnode.children
324333
const ch = vnode.children
325-
if (hasData) {
334+
if (hasData && isPatchable(vnode)) {
326335
for (i = 0; i < cbs.update.length; ++i) cbs.update[i](oldVnode, vnode)
327336
if (isDef(hook) && isDef(i = hook.update)) i(oldVnode, vnode)
328337
}
@@ -467,8 +476,10 @@ export function createPatchFunction (backend) {
467476
// update parent placeholder node element.
468477
if (vnode.parent) {
469478
vnode.parent.elm = vnode.elm
470-
for (let i = 0; i < cbs.create.length; ++i) {
471-
cbs.create[i](emptyNode, vnode.parent)
479+
if (isPatchable(vnode)) {
480+
for (let i = 0; i < cbs.create.length; ++i) {
481+
cbs.create[i](emptyNode, vnode.parent)
482+
}
472483
}
473484
}
474485

test/unit/features/directives/if.spec.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,4 +144,31 @@ describe('Directive v-if', () => {
144144
expect(vm.$el.innerHTML.trim()).toBe('<span>bye</span><span>hello</span>')
145145
}).then(done)
146146
})
147+
148+
it('should work properly on component root', done => {
149+
const vm = new Vue({
150+
template: `
151+
<div>
152+
<test class="test"></test>
153+
</div>
154+
`,
155+
components: {
156+
test: {
157+
data () {
158+
return { ok: true }
159+
},
160+
template: '<div v-if="ok" id="ok" class="inner">test</div>'
161+
}
162+
}
163+
}).$mount()
164+
expect(vm.$el.innerHTML).toBe('<div id="ok" class="inner test">test</div>')
165+
vm.$children[0].ok = false
166+
waitForUpdate(() => {
167+
// attrs / class modules should not attempt to patch the comment node
168+
expect(vm.$el.innerHTML).toBe('<!---->')
169+
vm.$children[0].ok = true
170+
}).then(() => {
171+
expect(vm.$el.innerHTML).toBe('<div id="ok" class="inner test">test</div>')
172+
}).then(done)
173+
})
147174
})

test/unit/features/options/directives.spec.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ describe('Options directives', () => {
3333
updateSpy()
3434
assertContext(el, binding, vnode)
3535
expect(el).toBe(vm.$el)
36-
expect(oldVnode).toBe(vm._vnode)
3736
expect(oldVnode).not.toBe(vnode)
3837
expect(binding.expression).toBe('a')
3938
if (binding.value !== binding.oldValue) {

test/unit/features/transition/transition.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,7 @@ if (!isIE9) {
558558
}).then(done)
559559
})
560560

561-
fit('transition with v-show, with transition outside and v-show inside', done => {
561+
it('transition with v-show, with transition outside and v-show inside', done => {
562562
const vm = new Vue({
563563
template: `
564564
<div>

0 commit comments

Comments
 (0)