fix(hmr): force full update in child component on slot update
This commit is contained in:
		
							parent
							
								
									5ddd9d2417
								
							
						
					
					
						commit
						2408a65662
					
				| @ -45,7 +45,7 @@ describe('hot module replacement', () => { | ||||
| 
 | ||||
|     const Child: ComponentOptions = { | ||||
|       __hmrId: childId, | ||||
|       render: compileToFunction(`<slot/>`) | ||||
|       render: compileToFunction(`<div><slot/></div>`) | ||||
|     } | ||||
|     createRecord(childId, Child) | ||||
| 
 | ||||
| @ -62,13 +62,13 @@ describe('hot module replacement', () => { | ||||
|     createRecord(parentId, Parent) | ||||
| 
 | ||||
|     render(h(Parent), root) | ||||
|     expect(serializeInner(root)).toBe(`<div>00</div>`) | ||||
|     expect(serializeInner(root)).toBe(`<div>0<div>0</div></div>`) | ||||
| 
 | ||||
|     // Perform some state change. This change should be preserved after the
 | ||||
|     // re-render!
 | ||||
|     triggerEvent(root.children[0] as TestElement, 'click') | ||||
|     await nextTick() | ||||
|     expect(serializeInner(root)).toBe(`<div>11</div>`) | ||||
|     expect(serializeInner(root)).toBe(`<div>1<div>1</div></div>`) | ||||
| 
 | ||||
|     // // Update text while preserving state
 | ||||
|     rerender( | ||||
| @ -77,7 +77,7 @@ describe('hot module replacement', () => { | ||||
|         `<div @click="count++">{{ count }}!<Child>{{ count }}</Child></div>` | ||||
|       ) | ||||
|     ) | ||||
|     expect(serializeInner(root)).toBe(`<div>1!1</div>`) | ||||
|     expect(serializeInner(root)).toBe(`<div>1!<div>1</div></div>`) | ||||
| 
 | ||||
|     // Should force child update on slot content change
 | ||||
|     rerender( | ||||
| @ -86,7 +86,7 @@ describe('hot module replacement', () => { | ||||
|         `<div @click="count++">{{ count }}!<Child>{{ count }}!</Child></div>` | ||||
|       ) | ||||
|     ) | ||||
|     expect(serializeInner(root)).toBe(`<div>1!1!</div>`) | ||||
|     expect(serializeInner(root)).toBe(`<div>1!<div>1!</div></div>`) | ||||
| 
 | ||||
|     // Should force update element children despite block optimization
 | ||||
|     rerender( | ||||
| @ -97,7 +97,7 @@ describe('hot module replacement', () => { | ||||
|       </div>` | ||||
|       ) | ||||
|     ) | ||||
|     expect(serializeInner(root)).toBe(`<div>1<span>1</span>1!</div>`) | ||||
|     expect(serializeInner(root)).toBe(`<div>1<span>1</span><div>1!</div></div>`) | ||||
| 
 | ||||
|     // Should force update child slot elements
 | ||||
|     rerender( | ||||
| @ -108,7 +108,7 @@ describe('hot module replacement', () => { | ||||
|       </div>` | ||||
|       ) | ||||
|     ) | ||||
|     expect(serializeInner(root)).toBe(`<div><span>1</span></div>`) | ||||
|     expect(serializeInner(root)).toBe(`<div><div><span>1</span></div></div>`) | ||||
|   }) | ||||
| 
 | ||||
|   test('reload', async () => { | ||||
|  | ||||
| @ -313,7 +313,7 @@ export interface ComponentInternalInstance { | ||||
|    * hmr marker (dev only) | ||||
|    * @internal | ||||
|    */ | ||||
|   renderUpdated?: boolean | ||||
|   hmrUpdated?: boolean | ||||
| } | ||||
| 
 | ||||
| const emptyAppContext = createAppContext() | ||||
|  | ||||
| @ -251,7 +251,7 @@ export function shouldUpdateComponent( | ||||
|     __DEV__ && | ||||
|     (prevChildren || nextChildren) && | ||||
|     parentComponent && | ||||
|     parentComponent.renderUpdated | ||||
|     parentComponent.hmrUpdated | ||||
|   ) { | ||||
|     return true | ||||
|   } | ||||
|  | ||||
| @ -18,6 +18,7 @@ import { | ||||
| import { warn } from './warning' | ||||
| import { isKeepAlive } from './components/KeepAlive' | ||||
| import { withCtx } from './helpers/withRenderContext' | ||||
| import { queuePostFlushCb } from './scheduler' | ||||
| 
 | ||||
| export type Slot = (...args: any[]) => VNode[] | ||||
| 
 | ||||
| @ -124,11 +125,17 @@ export const updateSlots = ( | ||||
|   if (vnode.shapeFlag & ShapeFlags.SLOTS_CHILDREN) { | ||||
|     if ((children as RawSlots)._ === 1) { | ||||
|       // compiled slots.
 | ||||
|       if ( | ||||
|       if (__DEV__ && instance.parent && instance.parent.hmrUpdated) { | ||||
|         // Parent was HMR updated so slot content may have changed.
 | ||||
|         // force update slots and mark instance for hmr as well
 | ||||
|         extend(slots, children as Slots) | ||||
|         instance.hmrUpdated = true | ||||
|         queuePostFlushCb(() => { | ||||
|           instance.hmrUpdated = false | ||||
|         }) | ||||
|       } else if ( | ||||
|         // bail on dynamic slots (v-if, v-for, reference of scope variables)
 | ||||
|         !(vnode.patchFlag & PatchFlags.DYNAMIC_SLOTS) && | ||||
|         // bail on HRM updates
 | ||||
|         !(__DEV__ && instance.parent && instance.parent.renderUpdated) | ||||
|         !(vnode.patchFlag & PatchFlags.DYNAMIC_SLOTS) | ||||
|       ) { | ||||
|         // compiled AND static.
 | ||||
|         // no need to update, and skip stale slots removal.
 | ||||
|  | ||||
| @ -70,9 +70,9 @@ function rerender(id: string, newRender?: Function) { | ||||
|     } | ||||
|     instance.renderCache = [] | ||||
|     // this flag forces child components with slot content to update
 | ||||
|     instance.renderUpdated = true | ||||
|     instance.hmrUpdated = true | ||||
|     instance.update() | ||||
|     instance.renderUpdated = false | ||||
|     instance.hmrUpdated = false | ||||
|   }) | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -779,7 +779,7 @@ function baseCreateRenderer( | ||||
|       invokeDirectiveHook(n2, n1, parentComponent, 'beforeUpdate') | ||||
|     } | ||||
| 
 | ||||
|     if (__DEV__ && parentComponent && parentComponent.renderUpdated) { | ||||
|     if (__DEV__ && parentComponent && parentComponent.hmrUpdated) { | ||||
|       // HMR updated, force full diff
 | ||||
|       patchFlag = 0 | ||||
|       optimized = false | ||||
| @ -1006,7 +1006,7 @@ function baseCreateRenderer( | ||||
|       optimized = true | ||||
|     } | ||||
| 
 | ||||
|     if (__DEV__ && parentComponent && parentComponent.renderUpdated) { | ||||
|     if (__DEV__ && parentComponent && parentComponent.hmrUpdated) { | ||||
|       // HMR updated, force full diff
 | ||||
|       patchFlag = 0 | ||||
|       optimized = false | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user