From 1b946c85df3d213900faccfa0723d736fa0927a3 Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 11 May 2020 14:17:35 -0400 Subject: [PATCH] fix(hmr): always force full child component props update in HMR mode --- packages/runtime-core/__tests__/hmr.spec.ts | 85 +++++++++++++++++++-- packages/runtime-core/src/renderer.ts | 3 + 2 files changed, 81 insertions(+), 7 deletions(-) diff --git a/packages/runtime-core/__tests__/hmr.spec.ts b/packages/runtime-core/__tests__/hmr.spec.ts index 8a141fe5f45..e23a222ff2a 100644 --- a/packages/runtime-core/__tests__/hmr.spec.ts +++ b/packages/runtime-core/__tests__/hmr.spec.ts @@ -71,13 +71,13 @@ describe('hot module replacement', () => { expect(serializeInner(root)).toBe(`
11
`) // // Update text while preserving state - // rerender( - // parentId, - // compileToFunction( - // `
{{ count }}!{{ count }}
` - // ) - // ) - // expect(serializeInner(root)).toBe(`
1!1
`) + rerender( + parentId, + compileToFunction( + `
{{ count }}!{{ count }}
` + ) + ) + expect(serializeInner(root)).toBe(`
1!1
`) // Should force child update on slot content change rerender( @@ -147,4 +147,75 @@ describe('hot module replacement', () => { expect(unmountSpy).toHaveBeenCalledTimes(1) expect(mountSpy).toHaveBeenCalledTimes(1) }) + + // #1156 - static nodes should retain DOM element reference across updates + // when HMR is active + test('static el reference', async () => { + const root = nodeOps.createElement('div') + const id = 'test-static-el' + + const template = `
+
{{ count }}
+ +
` + + const Comp: ComponentOptions = { + __hmrId: id, + data() { + return { count: 0 } + }, + render: compileToFunction(template) + } + createRecord(id, Comp) + + render(h(Comp), root) + expect(serializeInner(root)).toBe( + `
0
` + ) + + // 1. click to trigger update + triggerEvent((root as any).children[0].children[1], 'click') + await nextTick() + expect(serializeInner(root)).toBe( + `
1
` + ) + + // 2. trigger HMR + rerender( + id, + compileToFunction(template.replace(`
1
` + ) + }) + + // #1157 - component should force full props update when HMR is active + test('force update child component w/ static props', () => { + const root = nodeOps.createElement('div') + const parentId = 'test2-parent' + const childId = 'test2-child' + + const Child: ComponentOptions = { + __hmrId: childId, + props: { + msg: String + }, + render: compileToFunction(`
{{ msg }}
`) + } + createRecord(childId, Child) + + const Parent: ComponentOptions = { + __hmrId: parentId, + components: { Child }, + render: compileToFunction(``) + } + createRecord(parentId, Parent) + + render(h(Parent), root) + expect(serializeInner(root)).toBe(`
foo
`) + + rerender(parentId, compileToFunction(``)) + expect(serializeInner(root)).toBe(`
bar
`) + }) }) diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index 956f3326914..359648b5312 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -1270,6 +1270,9 @@ function baseCreateRenderer( nextVNode: VNode, optimized: boolean ) => { + if (__DEV__ && instance.type.__hmrId) { + optimized = false + } nextVNode.component = instance const prevProps = instance.vnode.props instance.vnode = nextVNode