diff --git a/src/share.ts b/src/share.ts index 3eed83e..c334417 100644 --- a/src/share.ts +++ b/src/share.ts @@ -1,24 +1,54 @@ import { useEffect, useReducer, useRef } from 'react'; import { effect, stop, ReactiveEffect } from '@vue/reactivity'; +type TVueEffectParameters = Parameters; + export const useForceUpdate = () => { const [, forceUpdate] = useReducer(s => s + 1, 0); return forceUpdate; }; -export const useEffection = (...effectArgs: Parameters) => { +export const useEffection = ( + fn: TVueEffectParameters[0], + options?: TVueEffectParameters[1], + changes?: any[] +) => { // 用一个ref存储effection // effect函数只需要初始化执行一遍 - const effectionRef = useRef(); + const effectionRef = useRef<{ + effect: ReactiveEffect, + changes: any[] | undefined + }>(); if (!effectionRef.current) { - effectionRef.current = effect(...effectArgs); + effectionRef.current = { + effect: effect(fn, options), + changes: changes, + }; + } else if (changes && changes.length && compare(effectionRef.current.changes, changes)) { + // 当旧的变化数据与新的变化数据的索引数据上的不一致 + // 我们需要销毁之前的effect + stop(effectionRef.current.effect); + // 重新创建新的effect + effectionRef.current = { + effect: effect(fn, options), + changes: changes, + }; } // 卸载组件后取消effect const stopEffect = () => { - stop(effectionRef.current!); + stop(effectionRef.current?.effect!); }; useEffect(() => stopEffect, []); - return effectionRef.current + return effectionRef.current.effect; }; + +function compare(oldChanges: any[] | undefined, newChanges: any[]) { + oldChanges = oldChanges || []; + if (oldChanges.length !== newChanges.length) return true; + for (let i = 0; i < newChanges.length; i++) { + if (oldChanges[i] !== newChanges[i]) return true; + } + return false; +} diff --git a/src/store.ts b/src/store.ts index 2df08d2..0b49bfc 100644 --- a/src/store.ts +++ b/src/store.ts @@ -19,7 +19,7 @@ const useStoreContext = () => { * 在组件中读取全局状态 * 需要通过传入的函数收集依赖 */ -export const useStore = (selector: Selector): S => { +export const useStore = (selector: Selector, changes?: any[]): S => { const forceUpdate = useForceUpdate(); const store = useStoreContext(); @@ -29,7 +29,7 @@ export const useStore = (selector: Selector): S => { forceUpdate(); }, lazy: true, - }); + }, changes); const value = effection(); return value;