From 6e19d6b6af2b9896887b735ae6a000ccf08710b2 Mon Sep 17 00:00:00 2001 From: * <8> Date: Wed, 26 Jan 2022 10:45:38 +0800 Subject: [PATCH] Match-id-eb73774c1a152584504f6ce5531febfedfcf3b83 --- .../src/renderer/submit/LifeCycleHandler.ts | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/libs/horizon/src/renderer/submit/LifeCycleHandler.ts b/libs/horizon/src/renderer/submit/LifeCycleHandler.ts index 398709df..68503458 100644 --- a/libs/horizon/src/renderer/submit/LifeCycleHandler.ts +++ b/libs/horizon/src/renderer/submit/LifeCycleHandler.ts @@ -309,23 +309,34 @@ function unmountDomComponents(vNode: VNode): void { function submitClear(vNode: VNode): void { const realNode = vNode.realNode; - const cloneDom = realNode.cloneNode(false); // 复制节点后horizon的两个属性消失 - const customizeKeys = Object.keys; + const cloneDom = realNode.cloneNode(false); // 复制节点后horizon添加给dom的属性未能复制 + // 真实 dom 获取的keys只包含新增的属性 + // 比如真实 dom 拿到的 keys 一般只有两个 horizon 自定义属性 + // 但考虑到用户可能自定义其他属性,所以采用遍历赋值的方式 + const customizeKeys = Object.keys(realNode); const keyLength = customizeKeys.length; for(let i = 0; i < keyLength; i++) { const key = customizeKeys[i]; - cloneDom[key] = realNode(key); + // 测试代码 mock 实例的全部可遍历属性都会被Object.keys方法读取到 + // children 属性被复制意味着复制了子节点,因此要排除 + if (key !== 'children') { + cloneDom[key] = realNode[key]; // 复制cloneNode未能复制的属性 + } } const parentObj = findDomParent(vNode); const currentParent = parentObj.parentDom; - const clearChild = vNode.clearChild as VNode; - // 卸载子vNode,递归遍历子vNode - unmountNestedVNodes(clearChild); // node.child 为空,需要添加原有的child + let clearChild = vNode.clearChild as VNode; // 上次渲染的child保存在clearChild属性中 + // 卸载 clearChild 和 它的兄弟节点 + while(clearChild) { + // 卸载子vNode,递归遍历子vNode + unmountNestedVNodes(clearChild); + clearVNode(clearChild); + clearChild = clearChild.next as VNode; + } // 在所有子项都卸载后,删除dom树中的节点 removeChildDom(currentParent, vNode.realNode); - clearVNode(clearChild); currentParent.append(cloneDom); vNode.realNode = cloneDom; FlagUtils.removeFlag(vNode, Clear);