From 2ba2d78d4f5781bff0c89ee0f4f69c84c1edbcd0 Mon Sep 17 00:00:00 2001 From: * <8> Date: Thu, 7 Jul 2022 16:57:14 +0800 Subject: [PATCH] Match-id-99816485a3994e661f2c58e75d8f852e44192ecc --- libs/horizon/src/renderer/ContextSaver.ts | 19 ++++- libs/horizon/src/renderer/TreeBuilder.ts | 6 +- .../__tests__/ComponentTest/Context.test.js | 75 +++++++++++++++++++ 3 files changed, 97 insertions(+), 3 deletions(-) diff --git a/libs/horizon/src/renderer/ContextSaver.ts b/libs/horizon/src/renderer/ContextSaver.ts index cd21da0b..2e72ce3c 100644 --- a/libs/horizon/src/renderer/ContextSaver.ts +++ b/libs/horizon/src/renderer/ContextSaver.ts @@ -45,13 +45,28 @@ export function resetContext(providerVNode: VNode) { context.value = providerVNode.context; } -// 在局部更新时,恢复父节点的context +// 在局部更新时,从上到下恢复父节点的context export function recoverParentContext(vNode: VNode) { + const contextProviders: VNode[] = []; + let parent = vNode.parent; + while (parent !== null) { + if (parent.tag === ContextProvider) { + contextProviders.unshift(parent); + } + parent = parent.parent; + } + contextProviders.forEach(node => { + setContext(node, node.props.value); + }); +} + +// 在局部更新时,从下到上重置父节点的context +export function resetParentContext(vNode: VNode) { let parent = vNode.parent; while (parent !== null) { if (parent.tag === ContextProvider) { - setContext(parent, parent.props.value); + resetContext(parent); } parent = parent.parent; } diff --git a/libs/horizon/src/renderer/TreeBuilder.ts b/libs/horizon/src/renderer/TreeBuilder.ts index 32bc6c14..c8b81ae7 100644 --- a/libs/horizon/src/renderer/TreeBuilder.ts +++ b/libs/horizon/src/renderer/TreeBuilder.ts @@ -29,7 +29,7 @@ import { isExecuting, setExecuteMode } from './ExecuteMode'; -import { recoverParentContext, resetNamespaceCtx, setNamespaceCtx } from './ContextSaver'; +import { recoverParentContext, resetParentContext, resetNamespaceCtx, setNamespaceCtx } from './ContextSaver'; import { updateChildShouldUpdate, updateParentsChildShouldUpdate, @@ -263,6 +263,10 @@ function buildVNodeTree(treeRoot: VNode) { handleError(treeRoot, thrownValue); } } + if (startVNode.tag !== TreeRoot) { // 不是根节点 + // 恢复父节点的context + resetParentContext(startVNode); + } setProcessingClassVNode(null); diff --git a/scripts/__tests__/ComponentTest/Context.test.js b/scripts/__tests__/ComponentTest/Context.test.js index d64934ef..14423b34 100644 --- a/scripts/__tests__/ComponentTest/Context.test.js +++ b/scripts/__tests__/ComponentTest/Context.test.js @@ -358,4 +358,79 @@ describe('Context Test', () => { Horizon.render(, container); expect(container.querySelector('p').innerHTML).toBe('Num: 8, Type: typeR'); }); + + // antd menu 级连context场景,menu路径使用级联context实现 + it('nested context', () => { + const NestedContext = Horizon.createContext([]); + let updateContext; + + function App() { + const [state, useState] = Horizon.useState([]); + updateContext = useState; + return ( + + + + + ); + } + + const div1Ref = Horizon.createRef(); + const div2Ref = Horizon.createRef(); + + let updateSub1; + function Sub1() { + const path = Horizon.useContext(NestedContext); + const [_, setState] = Horizon.useState({}); + updateSub1 = () => setState({}); + return ( + + + + ); + } + + function Sub2() { + const path = Horizon.useContext(NestedContext); + + return ( + + + + ); + } + + function Sub3() { + const path = Horizon.useContext(NestedContext); + + return ( + + + + ); + } + + function Son({ divRef }) { + const path = Horizon.useContext(NestedContext); + return ( + +
{path.join(',')}
+
+ ); + } + + Horizon.render(, container); + updateSub1(); + expect(div1Ref.current.innerHTML).toEqual('1'); + expect(div2Ref.current.innerHTML).toEqual('2,3'); + + updateContext([0]); + expect(div1Ref.current.innerHTML).toEqual('0,1'); + expect(div2Ref.current.innerHTML).toEqual('0,2,3'); + + // 局部更新Sub1 + updateSub1(); + expect(div1Ref.current.innerHTML).toEqual('0,1'); + expect(div2Ref.current.innerHTML).toEqual('0,2,3'); + }); });