@@ -12,7 +12,7 @@ import { ComponentOptions, ComponentInternalInstance } from './component'
12
12
import { invokeDirectiveHook } from './directives'
13
13
import { warn } from './warning'
14
14
import { PatchFlags , ShapeFlags , isReservedProp , isOn } from '@vue/shared'
15
- import { RendererInternals , invokeVNodeHook } from './renderer'
15
+ import { RendererInternals , invokeVNodeHook , setRef } from './renderer'
16
16
import {
17
17
SuspenseImpl ,
18
18
SuspenseBoundary ,
@@ -88,74 +88,85 @@ export function createHydrationFunctions(
88
88
isFragmentStart
89
89
)
90
90
91
- const { type, shapeFlag } = vnode
91
+ const { type, ref , shapeFlag } = vnode
92
92
const domType = node . nodeType
93
93
vnode . el = node
94
94
95
+ let nextNode : Node | null = null
95
96
switch ( type ) {
96
97
case Text :
97
98
if ( domType !== DOMNodeTypes . TEXT ) {
98
- return onMismatch ( )
99
- }
100
- if ( ( node as Text ) . data !== vnode . children ) {
101
- hasMismatch = true
102
- __DEV__ &&
103
- warn (
104
- `Hydration text mismatch:` +
105
- `\n- Client: ${ JSON . stringify ( ( node as Text ) . data ) } ` +
106
- `\n- Server: ${ JSON . stringify ( vnode . children ) } `
107
- )
108
- ; ( node as Text ) . data = vnode . children as string
99
+ nextNode = onMismatch ( )
100
+ } else {
101
+ if ( ( node as Text ) . data !== vnode . children ) {
102
+ hasMismatch = true
103
+ __DEV__ &&
104
+ warn (
105
+ `Hydration text mismatch:` +
106
+ `\n- Client: ${ JSON . stringify ( ( node as Text ) . data ) } ` +
107
+ `\n- Server: ${ JSON . stringify ( vnode . children ) } `
108
+ )
109
+ ; ( node as Text ) . data = vnode . children as string
110
+ }
111
+ nextNode = nextSibling ( node )
109
112
}
110
- return nextSibling ( node )
113
+ break
111
114
case Comment :
112
115
if ( domType !== DOMNodeTypes . COMMENT || isFragmentStart ) {
113
- return onMismatch ( )
116
+ nextNode = onMismatch ( )
117
+ } else {
118
+ nextNode = nextSibling ( node )
114
119
}
115
- return nextSibling ( node )
120
+ break
116
121
case Static :
117
122
if ( domType !== DOMNodeTypes . ELEMENT ) {
118
- return onMismatch ( )
119
- }
120
- // determine anchor, adopt content
121
- let cur = node
122
- // if the static vnode has its content stripped during build,
123
- // adopt it from the server-rendered HTML.
124
- const needToAdoptContent = ! ( vnode . children as string ) . length
125
- for ( let i = 0 ; i < vnode . staticCount ; i ++ ) {
126
- if ( needToAdoptContent ) vnode . children += ( cur as Element ) . outerHTML
127
- if ( i === vnode . staticCount - 1 ) {
128
- vnode . anchor = cur
123
+ nextNode = onMismatch ( )
124
+ } else {
125
+ // determine anchor, adopt content
126
+ nextNode = node
127
+ // if the static vnode has its content stripped during build,
128
+ // adopt it from the server-rendered HTML.
129
+ const needToAdoptContent = ! ( vnode . children as string ) . length
130
+ for ( let i = 0 ; i < vnode . staticCount ; i ++ ) {
131
+ if ( needToAdoptContent )
132
+ vnode . children += ( nextNode as Element ) . outerHTML
133
+ if ( i === vnode . staticCount - 1 ) {
134
+ vnode . anchor = nextNode
135
+ }
136
+ nextNode = nextSibling ( nextNode ) !
129
137
}
130
- cur = nextSibling ( cur ) !
138
+ return nextNode
131
139
}
132
- return cur
140
+ break
133
141
case Fragment :
134
142
if ( ! isFragmentStart ) {
135
- return onMismatch ( )
143
+ nextNode = onMismatch ( )
144
+ } else {
145
+ nextNode = hydrateFragment (
146
+ node as Comment ,
147
+ vnode ,
148
+ parentComponent ,
149
+ parentSuspense ,
150
+ optimized
151
+ )
136
152
}
137
- return hydrateFragment (
138
- node as Comment ,
139
- vnode ,
140
- parentComponent ,
141
- parentSuspense ,
142
- optimized
143
- )
153
+ break
144
154
default :
145
155
if ( shapeFlag & ShapeFlags . ELEMENT ) {
146
156
if (
147
157
domType !== DOMNodeTypes . ELEMENT ||
148
158
vnode . type !== ( node as Element ) . tagName . toLowerCase ( )
149
159
) {
150
- return onMismatch ( )
160
+ nextNode = onMismatch ( )
161
+ } else {
162
+ nextNode = hydrateElement (
163
+ node as Element ,
164
+ vnode ,
165
+ parentComponent ,
166
+ parentSuspense ,
167
+ optimized
168
+ )
151
169
}
152
- return hydrateElement (
153
- node as Element ,
154
- vnode ,
155
- parentComponent ,
156
- parentSuspense ,
157
- optimized
158
- )
159
170
} else if ( shapeFlag & ShapeFlags . COMPONENT ) {
160
171
// when setting up the render effect, if the initial vnode already
161
172
// has .el set, the component will perform hydration instead of mount
@@ -182,24 +193,25 @@ export function createHydrationFunctions(
182
193
// component may be async, so in the case of fragments we cannot rely
183
194
// on component's rendered output to determine the end of the fragment
184
195
// instead, we do a lookahead to find the end anchor node.
185
- return isFragmentStart
196
+ nextNode = isFragmentStart
186
197
? locateClosingAsyncAnchor ( node )
187
198
: nextSibling ( node )
188
199
} else if ( shapeFlag & ShapeFlags . TELEPORT ) {
189
200
if ( domType !== DOMNodeTypes . COMMENT ) {
190
- return onMismatch ( )
201
+ nextNode = onMismatch ( )
202
+ } else {
203
+ nextNode = ( vnode . type as typeof TeleportImpl ) . hydrate (
204
+ node ,
205
+ vnode ,
206
+ parentComponent ,
207
+ parentSuspense ,
208
+ optimized ,
209
+ rendererInternals ,
210
+ hydrateChildren
211
+ )
191
212
}
192
- return ( vnode . type as typeof TeleportImpl ) . hydrate (
193
- node ,
194
- vnode ,
195
- parentComponent ,
196
- parentSuspense ,
197
- optimized ,
198
- rendererInternals ,
199
- hydrateChildren
200
- )
201
213
} else if ( __FEATURE_SUSPENSE__ && shapeFlag & ShapeFlags . SUSPENSE ) {
202
- return ( vnode . type as typeof SuspenseImpl ) . hydrate (
214
+ nextNode = ( vnode . type as typeof SuspenseImpl ) . hydrate (
203
215
node ,
204
216
vnode ,
205
217
parentComponent ,
@@ -212,8 +224,13 @@ export function createHydrationFunctions(
212
224
} else if ( __DEV__ ) {
213
225
warn ( 'Invalid HostVNode type:' , type , `(${ typeof type } )` )
214
226
}
215
- return null
216
227
}
228
+
229
+ if ( ref != null && parentComponent ) {
230
+ setRef ( ref , null , parentComponent , vnode )
231
+ }
232
+
233
+ return nextNode
217
234
}
218
235
219
236
const hydrateElement = (
@@ -386,7 +403,7 @@ export function createHydrationFunctions(
386
403
parentComponent : ComponentInternalInstance | null ,
387
404
parentSuspense : SuspenseBoundary | null ,
388
405
isFragment : boolean
389
- ) => {
406
+ ) : Node | null => {
390
407
hasMismatch = true
391
408
__DEV__ &&
392
409
warn (
0 commit comments