File tree Expand file tree Collapse file tree 4 files changed +55
-4
lines changed Expand file tree Collapse file tree 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', () => {
148148 expect ( mountSpy ) . toHaveBeenCalledTimes ( 1 )
149149 } )
150150
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+
151194 // #1156 - static nodes should retain DOM element reference across updates
152195 // when HMR is active
153196 test ( 'static el reference' , async ( ) => {
Original file line number Diff line number Diff line change @@ -800,3 +800,7 @@ export function formatComponentName(
800800
801801 return name ? classify ( name ) : isRoot ? `App` : `Anonymous`
802802}
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 33 ConcreteComponent ,
44 ComponentInternalInstance ,
55 ComponentOptions ,
6- InternalRenderFunction
6+ InternalRenderFunction ,
7+ ClassComponent ,
8+ isClassComponent
79} from './component'
810import { queueJob , queuePostFlushCb } from './scheduler'
911import { extend } from '@vue/shared'
@@ -83,7 +85,7 @@ function rerender(id: string, newRender?: Function) {
8385 } )
8486}
8587
86- function reload ( id : string , newComp : ComponentOptions ) {
88+ function reload ( id : string , newComp : ComponentOptions | ClassComponent ) {
8789 const record = map . get ( id )
8890 if ( ! record ) return
8991 // Array.from creates a snapshot which avoids the set being mutated during
@@ -92,6 +94,7 @@ function reload(id: string, newComp: ComponentOptions) {
9294 const comp = instance . type
9395 if ( ! hmrDirtyComponents . has ( comp ) ) {
9496 // 1. Update existing comp definition to match new one
97+ newComp = isClassComponent ( newComp ) ? newComp . __vccOpts : newComp
9598 extend ( comp , newComp )
9699 for ( const key in comp ) {
97100 if ( ! ( key in newComp ) ) {
Original file line number Diff line number Diff line change @@ -17,7 +17,8 @@ import {
1717 Data ,
1818 ConcreteComponent ,
1919 ClassComponent ,
20- Component
20+ Component ,
21+ isClassComponent
2122} from './component'
2223import { RawSlots } from './componentSlots'
2324import { isProxy , Ref , toRaw , ReactiveFlags } from '@vue/reactivity'
@@ -340,7 +341,7 @@ function _createVNode(
340341 }
341342
342343 // class component normalization.
343- if ( isFunction ( type ) && '__vccOpts' in type ) {
344+ if ( isClassComponent ( type ) ) {
344345 type = type . __vccOpts
345346 }
346347
You can’t perform that action at this time.
0 commit comments