Match-id-cec2ce18d7d08f5b4f5642c57aaa799038a73223

This commit is contained in:
* 2022-08-24 17:29:09 +08:00
parent 5484fa748a
commit 5d8eebf144
3 changed files with 192 additions and 5 deletions

View File

@ -204,7 +204,8 @@ export function createStore<S extends object, A extends UserActions<S>, C extend
return createStoreHook(handler); return createStoreHook(handler);
} }
function clearVNodeObservers(vNode) { export function clearVNodeObservers(vNode) {
if(!vNode.observers) return;
vNode.observers.forEach(observer => { vNode.observers.forEach(observer => {
observer.clearByVNode(vNode); observer.clearByVNode(vNode);
}); });
@ -220,10 +221,7 @@ function hookStore() {
return; return;
} }
if (processingVNode.observers) { if (!processingVNode.observers) {
// 清除上一次缓存的Observer依赖
clearVNodeObservers(processingVNode);
} else {
processingVNode.observers = new Set<Observer>(); processingVNode.observers = new Set<Observer>();
} }

View File

@ -12,6 +12,7 @@ import { FlagUtils } from '../vnode/VNodeFlags';
import {onlyUpdateChildVNodes} from '../vnode/VNodeCreator'; import {onlyUpdateChildVNodes} from '../vnode/VNodeCreator';
import componentRenders from './index'; import componentRenders from './index';
import {setProcessingVNode} from '../GlobalVar'; import {setProcessingVNode} from '../GlobalVar';
import { clearVNodeObservers } from '../../horizonx/store/StoreHandler';
// 复用vNode时也需对stack进行处理 // 复用vNode时也需对stack进行处理
function handlerContext(processing: VNode) { function handlerContext(processing: VNode) {
@ -55,6 +56,8 @@ export function captureVNode(processing: VNode): VNode | null {
processing.shouldUpdate = false; processing.shouldUpdate = false;
setProcessingVNode(processing); setProcessingVNode(processing);
clearVNodeObservers(processing);
const child = component.captureRender(processing, shouldUpdate); const child = component.captureRender(processing, shouldUpdate);
setProcessingVNode(null); setProcessingVNode(null);

View File

@ -0,0 +1,186 @@
//@ts-ignore
import Horizon, { createStore } from '@cloudsop/horizon/index.ts';
import { triggerClickEvent } from '../../jest/commonComponents';
import { describe, beforeEach, afterEach, it, expect } from '@jest/globals';
const { unmountComponentAtNode } = Horizon;
const useStore1 = createStore({
state:{ counter:1 },
actions:{
add:(state)=>state.counter++,
reset: (state)=>state.counter=1
}
})
const useStore2 = createStore({
state:{ counter2:1 },
actions:{
add2:(state)=>state.counter2++,
reset: (state)=>state.counter2=1
}
})
describe('Using multiple stores', () => {
let container: HTMLElement | null = null;
const BUTTON_ID = 'btn';
const BUTTON_ID2 = 'btn2';
const RESULT_ID = 'result';
beforeEach(() => {
container = document.createElement('div');
document.body.appendChild(container);
useStore1().reset();
useStore2().reset();
});
afterEach(() => {
unmountComponentAtNode(container);
container?.remove();
container = null;
});
it('Should use multiple stores in class component', () => {
class App extends Horizon.Component{
render(){
const {counter,add} = useStore1();
const store2 = useStore2();
const {counter2, add2} = store2;
return (
<div>
<button
id={BUTTON_ID}
onClick={() => {
add();
}}
>
add
</button>
<button
id={BUTTON_ID2}
onClick={() => {
add2();
}}
>
add
</button>
<p id={RESULT_ID}>{counter*counter2}</p>
</div>
)
}
}
Horizon.render(<App />, container);
Horizon.act(() => {
triggerClickEvent(container, BUTTON_ID);
triggerClickEvent(container, BUTTON_ID);
triggerClickEvent(container, BUTTON_ID2);
triggerClickEvent(container, BUTTON_ID2);
});
expect(document.getElementById(RESULT_ID)?.innerHTML).toBe('9');
});
it('Should use use stores in cycles and multiple methods', () => {
interface App {
store:any,
store2:any
}
class App extends Horizon.Component{
constructor(){
super();
this.store = useStore1();
this.store2 = useStore2()
}
render(){
const {counter,add} = useStore1();
const store2 = useStore2();
const {counter2, add2} = store2;
for(let i=0; i<100; i++){
const {counter,add} = useStore1();
const store2 = useStore2();
const {counter2, add2} = store2;
}
return (
<div>
<button
id={BUTTON_ID}
onClick={() => {
add();
}}
>
add
</button>
<button
id={BUTTON_ID2}
onClick={() => {
this.store2.add2();
}}
>
add
</button>
<p id={RESULT_ID}>{counter*counter2}</p>
</div>
)
}
}
Horizon.render(<App />, container);
Horizon.act(() => {
triggerClickEvent(container, BUTTON_ID);
triggerClickEvent(container, BUTTON_ID);
triggerClickEvent(container, BUTTON_ID2);
triggerClickEvent(container, BUTTON_ID2);
});
expect(document.getElementById(RESULT_ID)?.innerHTML).toBe('9');
});
it('Should use multiple stores in function component', () => {
function App() {
const {counter,add} = useStore1();
const store2 = useStore2();
const {counter2, add2} = store2;
return (
<div>
<button
id={BUTTON_ID}
onClick={() => {
add();
}}
>
add
</button>
<button
id={BUTTON_ID2}
onClick={() => {
add2();
}}
>
add
</button>
<p id={RESULT_ID}>{counter*counter2}</p>
</div>
);
}
Horizon.render(<App />, container);
Horizon.act(() => {
triggerClickEvent(container, BUTTON_ID);
triggerClickEvent(container, BUTTON_ID);
triggerClickEvent(container, BUTTON_ID2);
triggerClickEvent(container, BUTTON_ID2);
});
expect(document.getElementById(RESULT_ID)?.innerHTML).toBe('9');
});
});