From b3e465614ca8d2523aff8e1f02e420c44932cc63 Mon Sep 17 00:00:00 2001 From: likui <2218301630@qq.com> Date: Sun, 14 Jun 2020 12:13:37 +0800 Subject: [PATCH 1/5] fix(runtime-core): should update parent host el when component self updated fix #1357 --- packages/runtime-core/src/renderer.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index 1d8bc712b59..48529d3c7cb 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -1304,6 +1304,7 @@ function baseCreateRenderer( // This is triggered by mutation of component's own state (next: null) // OR parent calling processComponent (next: VNode) let { next, bu, u, parent, vnode } = instance + let originNext = next let vnodeHook: VNodeHook | null | undefined if (__DEV__) { pushWarningContext(next || instance.vnode) @@ -1355,7 +1356,7 @@ function baseCreateRenderer( endMeasure(instance, `patch`) } next.el = nextTree.el - if (next === null) { + if (originNext === null) { // self-triggered update. In case of HOC, update parent component // vnode el. HOC is indicated by parent instance's subTree pointing // to child component's vnode From 97fa0a21edea4bf14721a34ad562b55d2d468d59 Mon Sep 17 00:00:00 2001 From: likui <2218301630@qq.com> Date: Sun, 14 Jun 2020 19:12:00 +0800 Subject: [PATCH 2/5] fix: update el with same type vnode --- packages/runtime-core/src/componentRenderUtils.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/runtime-core/src/componentRenderUtils.ts b/packages/runtime-core/src/componentRenderUtils.ts index 060e07f71d8..26bd1e265e7 100644 --- a/packages/runtime-core/src/componentRenderUtils.ts +++ b/packages/runtime-core/src/componentRenderUtils.ts @@ -11,7 +11,8 @@ import { cloneVNode, Fragment, VNodeArrayChildren, - isVNode + isVNode, + isSameVNodeType } from './vnode' import { handleError, ErrorCodes } from './errorHandling' import { PatchFlags, ShapeFlags, isOn } from '@vue/shared' @@ -318,8 +319,8 @@ export function updateHOCHostEl( { vnode, parent }: ComponentInternalInstance, el: typeof vnode.el // HostNode ) { - while (parent && parent.subTree === vnode) { - ;(vnode = parent.vnode).el = el + while (parent && isSameVNodeType(parent.subTree, vnode)) { + ;(vnode = parent.vnode).el = parent.subTree.el = el parent = parent.parent } } From 25a5600ecced3a99fb3cd5709cd088e26fef819b Mon Sep 17 00:00:00 2001 From: likui <2218301630@qq.com> Date: Mon, 15 Jun 2020 12:17:13 +0800 Subject: [PATCH 3/5] test: add test --- .../__tests__/rendererComponent.spec.ts | 44 +++++++++++++++++++ packages/runtime-core/src/renderer.ts | 1 + 2 files changed, 45 insertions(+) create mode 100644 packages/runtime-core/__tests__/rendererComponent.spec.ts diff --git a/packages/runtime-core/__tests__/rendererComponent.spec.ts b/packages/runtime-core/__tests__/rendererComponent.spec.ts new file mode 100644 index 00000000000..2bd611334cc --- /dev/null +++ b/packages/runtime-core/__tests__/rendererComponent.spec.ts @@ -0,0 +1,44 @@ +import { + ref, + h, + render, + nodeOps, + serializeInner, + nextTick, + VNode +} from '@vue/runtime-test' + +describe('renderer: component', () => { + test('should update parent(hoc) component host el when child component self update', async () => { + const value = ref(true) + let parentVnode: VNode + let childVnode1: VNode + let childVnode2: VNode + + const Parent = { + render: () => { + // let Parent first rerender + console.log(value.value) + return (parentVnode = h(Child)) + } + } + + const Child = { + render: () => { + return value.value + ? (childVnode1 = h('div')) + : (childVnode2 = h('span')) + } + } + + const root = nodeOps.createElement('div') + render(h(Parent), root) + expect(serializeInner(root)).toBe(`
`) + expect(parentVnode!.el).toBe(childVnode1!.el) + + value.value = false + await nextTick() + expect(serializeInner(root)).toBe(``) + expect(parentVnode!.el).toBe(childVnode2!.el) + }) +}) diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index 48529d3c7cb..f02543a9472 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -1216,6 +1216,7 @@ function baseCreateRenderer( // no update needed. just copy over properties n2.component = n1.component n2.el = n1.el + // instance.vnode = n2 } } From ad58f8e24e45abd294ecbdce3ac2f582e4d6d8aa Mon Sep 17 00:00:00 2001 From: likui <2218301630@qq.com> Date: Mon, 15 Jun 2020 13:06:23 +0800 Subject: [PATCH 4/5] fix: should update vnode when component not need updated --- packages/runtime-core/src/componentRenderUtils.ts | 5 ++--- packages/runtime-core/src/renderer.ts | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/runtime-core/src/componentRenderUtils.ts b/packages/runtime-core/src/componentRenderUtils.ts index 26bd1e265e7..ba35fd1955d 100644 --- a/packages/runtime-core/src/componentRenderUtils.ts +++ b/packages/runtime-core/src/componentRenderUtils.ts @@ -11,8 +11,7 @@ import { cloneVNode, Fragment, VNodeArrayChildren, - isVNode, - isSameVNodeType + isVNode } from './vnode' import { handleError, ErrorCodes } from './errorHandling' import { PatchFlags, ShapeFlags, isOn } from '@vue/shared' @@ -319,7 +318,7 @@ export function updateHOCHostEl( { vnode, parent }: ComponentInternalInstance, el: typeof vnode.el // HostNode ) { - while (parent && isSameVNodeType(parent.subTree, vnode)) { + while (parent && parent.subTree === vnode) { ;(vnode = parent.vnode).el = parent.subTree.el = el parent = parent.parent } diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index f02543a9472..edc00d1750d 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -1216,7 +1216,7 @@ function baseCreateRenderer( // no update needed. just copy over properties n2.component = n1.component n2.el = n1.el - // instance.vnode = n2 + instance.vnode = n2 } } From 57128eee2e0a011ce82db3ae0ad3424d1c9afab5 Mon Sep 17 00:00:00 2001 From: likui <2218301630@qq.com> Date: Mon, 15 Jun 2020 13:08:25 +0800 Subject: [PATCH 5/5] fix: revert --- packages/runtime-core/src/componentRenderUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/runtime-core/src/componentRenderUtils.ts b/packages/runtime-core/src/componentRenderUtils.ts index ba35fd1955d..060e07f71d8 100644 --- a/packages/runtime-core/src/componentRenderUtils.ts +++ b/packages/runtime-core/src/componentRenderUtils.ts @@ -319,7 +319,7 @@ export function updateHOCHostEl( el: typeof vnode.el // HostNode ) { while (parent && parent.subTree === vnode) { - ;(vnode = parent.vnode).el = parent.subTree.el = el + ;(vnode = parent.vnode).el = el parent = parent.parent } }