File tree 4 files changed +55
-4
lines changed
4 files changed +55
-4
lines changed Original file line number Diff line number Diff line change @@ -148,6 +148,49 @@ describe('hot module replacement', () => {
148
148
expect ( mountSpy ) . toHaveBeenCalledTimes ( 1 )
149
149
} )
150
150
151
+ test ( 'reload class component' , async ( ) => {
152
+ const root = nodeOps . createElement ( 'div' )
153
+ const childId = 'test4-child'
154
+ const unmountSpy = jest . fn ( )
155
+ const mountSpy = jest . fn ( )
156
+
157
+ class Child {
158
+ static __vccOpts : ComponentOptions = {
159
+ __hmrId : childId ,
160
+ data ( ) {
161
+ return { count : 0 }
162
+ } ,
163
+ unmounted : unmountSpy ,
164
+ render : compileToFunction ( `<div @click="count++">{{ count }}</div>` )
165
+ }
166
+ }
167
+ createRecord ( childId )
168
+
169
+ const Parent : ComponentOptions = {
170
+ render : ( ) => h ( Child )
171
+ }
172
+
173
+ render ( h ( Parent ) , root )
174
+ expect ( serializeInner ( root ) ) . toBe ( `<div>0</div>` )
175
+
176
+ class UpdatedChild {
177
+ static __vccOpts : ComponentOptions = {
178
+ __hmrId : childId ,
179
+ data ( ) {
180
+ return { count : 1 }
181
+ } ,
182
+ mounted : mountSpy ,
183
+ render : compileToFunction ( `<div @click="count++">{{ count }}</div>` )
184
+ }
185
+ }
186
+
187
+ reload ( childId , UpdatedChild )
188
+ await nextTick ( )
189
+ expect ( serializeInner ( root ) ) . toBe ( `<div>1</div>` )
190
+ expect ( unmountSpy ) . toHaveBeenCalledTimes ( 1 )
191
+ expect ( mountSpy ) . toHaveBeenCalledTimes ( 1 )
192
+ } )
193
+
151
194
// #1156 - static nodes should retain DOM element reference across updates
152
195
// when HMR is active
153
196
test ( 'static el reference' , async ( ) => {
Original file line number Diff line number Diff line change @@ -800,3 +800,7 @@ export function formatComponentName(
800
800
801
801
return name ? classify ( name ) : isRoot ? `App` : `Anonymous`
802
802
}
803
+
804
+ export function isClassComponent ( value : unknown ) : value is ClassComponent {
805
+ return isFunction ( value ) && '__vccOpts' in value
806
+ }
Original file line number Diff line number Diff line change 3
3
ConcreteComponent ,
4
4
ComponentInternalInstance ,
5
5
ComponentOptions ,
6
- InternalRenderFunction
6
+ InternalRenderFunction ,
7
+ ClassComponent ,
8
+ isClassComponent
7
9
} from './component'
8
10
import { queueJob , queuePostFlushCb } from './scheduler'
9
11
import { extend } from '@vue/shared'
@@ -83,7 +85,7 @@ function rerender(id: string, newRender?: Function) {
83
85
} )
84
86
}
85
87
86
- function reload ( id : string , newComp : ComponentOptions ) {
88
+ function reload ( id : string , newComp : ComponentOptions | ClassComponent ) {
87
89
const record = map . get ( id )
88
90
if ( ! record ) return
89
91
// Array.from creates a snapshot which avoids the set being mutated during
@@ -92,6 +94,7 @@ function reload(id: string, newComp: ComponentOptions) {
92
94
const comp = instance . type
93
95
if ( ! hmrDirtyComponents . has ( comp ) ) {
94
96
// 1. Update existing comp definition to match new one
97
+ newComp = isClassComponent ( newComp ) ? newComp . __vccOpts : newComp
95
98
extend ( comp , newComp )
96
99
for ( const key in comp ) {
97
100
if ( ! ( key in newComp ) ) {
Original file line number Diff line number Diff line change @@ -17,7 +17,8 @@ import {
17
17
Data ,
18
18
ConcreteComponent ,
19
19
ClassComponent ,
20
- Component
20
+ Component ,
21
+ isClassComponent
21
22
} from './component'
22
23
import { RawSlots } from './componentSlots'
23
24
import { isProxy , Ref , toRaw , ReactiveFlags } from '@vue/reactivity'
@@ -340,7 +341,7 @@ function _createVNode(
340
341
}
341
342
342
343
// class component normalization.
343
- if ( isFunction ( type ) && '__vccOpts' in type ) {
344
+ if ( isClassComponent ( type ) ) {
344
345
type = type . __vccOpts
345
346
}
346
347
You can’t perform that action at this time.
0 commit comments