From ae848e48f846ff10ed466a3bd13a82f27a12b601 Mon Sep 17 00:00:00 2001 From: HcySunYang Date: Fri, 26 Feb 2021 12:39:06 +0800 Subject: [PATCH 1/2] fix(Teleport): should check the optimized flag when Teleport performs update --- packages/runtime-core/__tests__/hmr.spec.ts | 61 +++++++++++++++++++ .../runtime-core/src/components/Teleport.ts | 5 +- 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/packages/runtime-core/__tests__/hmr.spec.ts b/packages/runtime-core/__tests__/hmr.spec.ts index ab2de223cdc..70af64853c5 100644 --- a/packages/runtime-core/__tests__/hmr.spec.ts +++ b/packages/runtime-core/__tests__/hmr.spec.ts @@ -332,4 +332,65 @@ describe('hot module replacement', () => { rerender(last.__hmrId!, compileToFunction(``)) expect(serializeInner(root)).toBe(`
child
`) }) + + // #3302 + test('rerender with Teleport', () => { + const root = nodeOps.createElement('div') + const target = nodeOps.createElement('div') + const parentId = 'parent-teleport' + + const Child: ComponentOptions = { + data() { + return { + // style is used to ensure that the div tag will be tracked by Teleport + style: {}, + target + } + }, + render: compileToFunction(` + +
+ +
+
+ `) + } + + const Parent: ComponentOptions = { + __hmrId: parentId, + components: { Child }, + render: compileToFunction(` + + + + `) + } + createRecord(parentId, Parent) + + render(h(Parent), root) + expect(serializeInner(root)).toBe( + `` + ) + expect(serializeInner(target)).toBe(`
1
`) + + rerender( + parentId, + compileToFunction(` + + + + `) + ) + expect(serializeInner(root)).toBe( + `` + ) + expect(serializeInner(target)).toBe( + `
1
2
` + ) + }) }) diff --git a/packages/runtime-core/src/components/Teleport.ts b/packages/runtime-core/src/components/Teleport.ts index fa61c636a88..05d8f0af5e2 100644 --- a/packages/runtime-core/src/components/Teleport.ts +++ b/packages/runtime-core/src/components/Teleport.ts @@ -135,8 +135,9 @@ export const TeleportImpl = { const currentContainer = wasDisabled ? container : target const currentAnchor = wasDisabled ? mainAnchor : targetAnchor isSVG = isSVG || isTargetSVG(target) - - if (n2.dynamicChildren) { + // #3302 + // HMR updates will force fall back to non-optimized mode + if (n2.dynamicChildren && optimized) { // fast path when the teleport happens to be a block root patchBlockChildren( n1.dynamicChildren!, From 6fe5a96f689e80aac75ff63ca5e8e91c3362e8a2 Mon Sep 17 00:00:00 2001 From: HcySunYang Date: Fri, 26 Feb 2021 13:33:57 +0800 Subject: [PATCH 2/2] chore: consistent way --- packages/runtime-core/src/components/Teleport.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/runtime-core/src/components/Teleport.ts b/packages/runtime-core/src/components/Teleport.ts index 05d8f0af5e2..a7b0227be8b 100644 --- a/packages/runtime-core/src/components/Teleport.ts +++ b/packages/runtime-core/src/components/Teleport.ts @@ -11,6 +11,7 @@ import { import { VNode, VNodeArrayChildren, VNodeProps } from '../vnode' import { isString, ShapeFlags } from '@vue/shared' import { warn } from '../warning' +import { isHmrUpdating } from '../hmr' export type TeleportVNode = VNode @@ -84,6 +85,13 @@ export const TeleportImpl = { const disabled = isTeleportDisabled(n2.props) const { shapeFlag, children } = n2 + // #3302 + // HMR updated, force full diff + if (__DEV__ && isHmrUpdating) { + optimized = false + n2.dynamicChildren = null + } + if (n1 == null) { // insert anchors in the main view const placeholder = (n2.el = __DEV__ @@ -135,9 +143,8 @@ export const TeleportImpl = { const currentContainer = wasDisabled ? container : target const currentAnchor = wasDisabled ? mainAnchor : targetAnchor isSVG = isSVG || isTargetSVG(target) - // #3302 - // HMR updates will force fall back to non-optimized mode - if (n2.dynamicChildren && optimized) { + + if (n2.dynamicChildren) { // fast path when the teleport happens to be a block root patchBlockChildren( n1.dynamicChildren!,