Match-id-99816485a3994e661f2c58e75d8f852e44192ecc

This commit is contained in:
* 2022-07-07 16:57:14 +08:00 committed by *
parent 2ca9803cd9
commit 2ba2d78d4f
3 changed files with 97 additions and 3 deletions

View File

@ -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;
}

View File

@ -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);

View File

@ -358,4 +358,79 @@ describe('Context Test', () => {
Horizon.render(<App num={8} type={'typeR'} />, 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 (
<NestedContext.Provider value={state}>
<Sub1 />
<Sub2 />
</NestedContext.Provider>
);
}
const div1Ref = Horizon.createRef();
const div2Ref = Horizon.createRef();
let updateSub1;
function Sub1() {
const path = Horizon.useContext(NestedContext);
const [_, setState] = Horizon.useState({});
updateSub1 = () => setState({});
return (
<NestedContext.Provider value={[...path, 1]}>
<Son divRef={div1Ref} />
</NestedContext.Provider>
);
}
function Sub2() {
const path = Horizon.useContext(NestedContext);
return (
<NestedContext.Provider value={[...path, 2]}>
<Sub3 />
</NestedContext.Provider>
);
}
function Sub3() {
const path = Horizon.useContext(NestedContext);
return (
<NestedContext.Provider value={[...path, 3]}>
<Son divRef={div2Ref} />
</NestedContext.Provider>
);
}
function Son({ divRef }) {
const path = Horizon.useContext(NestedContext);
return (
<NestedContext.Provider value={path}>
<div ref={divRef}>{path.join(',')}</div>
</NestedContext.Provider>
);
}
Horizon.render(<App />, 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');
});
});