Skip to content

Commit 6b1755a

Browse files
committed
adjust hydration strategy (fix vuejs#4560)
1 parent e120d14 commit 6b1755a

File tree

2 files changed

+32
-8
lines changed

2 files changed

+32
-8
lines changed

src/core/vdom/patch.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
import config from '../config'
1616
import VNode from './vnode'
17-
import { makeMap, isPrimitive, _toString, warn } from '../util/index'
17+
import { makeMap, isPrimitive, warn } from '../util/index'
1818
import { activeInstance } from '../instance/lifecycle'
1919
import { registerRef } from './modules/ref'
2020

@@ -526,6 +526,8 @@ export function createPatchFunction (backend) {
526526
}
527527
}
528528
}
529+
} else if (elm.data !== vnode.text) {
530+
elm.data = vnode.text
529531
}
530532
return true
531533
}
@@ -537,7 +539,7 @@ export function createPatchFunction (backend) {
537539
vnode.tag.toLowerCase() === (node.tagName && node.tagName.toLowerCase())
538540
)
539541
} else {
540-
return _toString(vnode.text) === node.data
542+
return node.nodeType === (vnode.isComment ? 8 : 3)
541543
}
542544
}
543545

test/unit/modules/vdom/patch/hydration.spec.js

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,14 +91,15 @@ describe('vdom patch: hydration', () => {
9191
it('should hydrate components when server-rendered DOM tree is same as virtual DOM tree', done => {
9292
const dom = document.createElement('div')
9393
dom.setAttribute('server-rendered', 'true')
94-
dom.innerHTML = '<span>foo</span><div class="b a"><span>foo qux</span></div>'
94+
dom.innerHTML = '<span>foo</span><div class="b a"><span>foo qux</span></div><!---->'
9595
const originalNode1 = dom.children[0]
9696
const originalNode2 = dom.children[1]
9797

9898
const vm = new Vue({
99-
template: '<div><span>{{msg}}</span><test class="a" :msg="msg"></test></div>',
99+
template: '<div><span>{{msg}}</span><test class="a" :msg="msg"></test><p v-if="ok"></p></div>',
100100
data: {
101-
msg: 'foo'
101+
msg: 'foo',
102+
ok: false
102103
},
103104
components: {
104105
test: {
@@ -119,14 +120,34 @@ describe('vdom patch: hydration', () => {
119120
expect(vm.$el.children[1]).toBe(originalNode2)
120121
vm.msg = 'bar'
121122
waitForUpdate(() => {
122-
expect(vm.$el.innerHTML).toBe('<span>bar</span><div class="b a"><span>bar qux</span></div>')
123+
expect(vm.$el.innerHTML).toBe('<span>bar</span><div class="b a"><span>bar qux</span></div><!---->')
123124
vm.$children[0].a = 'ququx'
124125
}).then(() => {
125-
expect(vm.$el.innerHTML).toBe('<span>bar</span><div class="b a"><span>bar ququx</span></div>')
126+
expect(vm.$el.innerHTML).toBe('<span>bar</span><div class="b a"><span>bar ququx</span></div><!---->')
127+
vm.ok = true
128+
}).then(() => {
129+
expect(vm.$el.innerHTML).toBe('<span>bar</span><div class="b a"><span>bar ququx</span></div><p></p>')
126130
}).then(done)
127131
})
128132

129133
it('should warn failed hydration for non-matching DOM in child component', () => {
134+
const dom = document.createElement('div')
135+
dom.setAttribute('server-rendered', 'true')
136+
dom.innerHTML = '<div><span></span></div>'
137+
138+
new Vue({
139+
template: '<div><test></test></div>',
140+
components: {
141+
test: {
142+
template: '<div><a></a></div>'
143+
}
144+
}
145+
}).$mount(dom)
146+
147+
expect('not matching server-rendered content').toHaveBeenWarned()
148+
})
149+
150+
it('should overwrite textNodes in the correct position but with mismatching text without warning', () => {
130151
const dom = document.createElement('div')
131152
dom.setAttribute('server-rendered', 'true')
132153
dom.innerHTML = '<div><span>foo</span></div>'
@@ -143,7 +164,8 @@ describe('vdom patch: hydration', () => {
143164
}
144165
}).$mount(dom)
145166

146-
expect('not matching server-rendered content').toHaveBeenWarned()
167+
expect('not matching server-rendered content').not.toHaveBeenWarned()
168+
expect(dom.querySelector('span').textContent).toBe('qux')
147169
})
148170

149171
it('should pick up elements with no children and populate without warning', done => {

0 commit comments

Comments
 (0)