From 0da51400bca17914f115cee8f98f713f13c8d0d8 Mon Sep 17 00:00:00 2001 From: Bowen Tan Date: Sun, 24 Apr 2022 17:13:05 +0800 Subject: [PATCH] add HiddenImplWrapper --- .../ImplWrapper/HiddenImplWrapper.tsx | 43 +++++++++++++++++++ .../_internal/ImplWrapper/ImplWrapper.tsx | 11 +++++ .../_internal/ImplWrapper/ImplWrapperMain.tsx | 10 +++++ .../_internal/ImplWrapper/hooks/useEleMap.tsx | 2 + .../ImplWrapper/hooks/useRuntimeFunctions.ts | 1 + packages/runtime/src/components/core/Text.tsx | 34 +++++++++++++-- packages/runtime/src/traits/core/Fetch.tsx | 1 + packages/runtime/src/traits/core/State.tsx | 1 + packages/runtime/src/traits/core/Style.tsx | 22 ++++++++++ 9 files changed, 122 insertions(+), 3 deletions(-) create mode 100644 packages/runtime/src/components/_internal/ImplWrapper/HiddenImplWrapper.tsx diff --git a/packages/runtime/src/components/_internal/ImplWrapper/HiddenImplWrapper.tsx b/packages/runtime/src/components/_internal/ImplWrapper/HiddenImplWrapper.tsx new file mode 100644 index 00000000..ef4560df --- /dev/null +++ b/packages/runtime/src/components/_internal/ImplWrapper/HiddenImplWrapper.tsx @@ -0,0 +1,43 @@ +import React, { useEffect, useMemo, useState } from 'react'; +import { ImplWrapperProps, TraitResult } from '../../../types'; +import { ImplWrapperMain } from './ImplWrapperMain'; +import { useRuntimeFunctions } from './hooks/useRuntimeFunctions'; + +export const HiddenImplWrapper = React.forwardRef( + (props, ref) => { + const { component: c, services } = props; + const { stateManager } = services; + const { executeTrait } = useRuntimeFunctions(props); + const hiddenTraits = useMemo( + () => c.traits.filter(t => t.type === 'core/v1/hidden'), + [c.traits] + ); + const [isHidden, setIsHidden] = useState(() => { + const results: TraitResult[] = hiddenTraits.map(t => { + const properties = stateManager.deepEval(t.properties); + return executeTrait(t, properties); + }); + return results.some(result => result.unmount); + }); + + useEffect(() => { + if (hiddenTraits.length > 0) { + hiddenTraits.map(t => { + const properties = stateManager.deepEvalAndWatch(t.properties, newV => { + console.log('get hidden results', newV.result.hidden); + const result = executeTrait(t, newV.result); + setIsHidden(!!result.unmount); + if (result.unmount) { + // // Every component's state is initialize in initStateAnd Method. + // // So if if it should not render, we should remove it from store. + delete stateManager.store[c.id]; + } + }); + return executeTrait(t, properties); + }); + } + }, [c, executeTrait, hiddenTraits, stateManager]); + + return !isHidden ? : null; + } +); diff --git a/packages/runtime/src/components/_internal/ImplWrapper/ImplWrapper.tsx b/packages/runtime/src/components/_internal/ImplWrapper/ImplWrapper.tsx index 9de9dec2..3caabd03 100644 --- a/packages/runtime/src/components/_internal/ImplWrapper/ImplWrapper.tsx +++ b/packages/runtime/src/components/_internal/ImplWrapper/ImplWrapper.tsx @@ -2,6 +2,17 @@ import React from 'react'; import { ImplWrapperProps } from '../../../types'; import { shallowCompareArray } from '../../../utils/shallowCompareArray'; import { ImplWrapperMain } from './ImplWrapperMain'; +// import { HiddenImplWrapper } from './HiddenImplWrapper'; + +// export const _ImplWrapper = React.forwardRef( +// (props, ref) => { +// return ( +// +// +// +// ); +// } +// ); export const ImplWrapper = React.memo( ImplWrapperMain, diff --git a/packages/runtime/src/components/_internal/ImplWrapper/ImplWrapperMain.tsx b/packages/runtime/src/components/_internal/ImplWrapper/ImplWrapperMain.tsx index bf39cb13..006d5298 100644 --- a/packages/runtime/src/components/_internal/ImplWrapper/ImplWrapperMain.tsx +++ b/packages/runtime/src/components/_internal/ImplWrapper/ImplWrapperMain.tsx @@ -12,6 +12,7 @@ import { useGridLayout } from './hooks/useGridLayout'; export const ImplWrapperMain = React.forwardRef( (props, ref) => { const { component: c, children } = props; + console.info('####ImplWrapper Render', c.id); const { registry, stateManager } = props.services; const Impl = registry.getComponent(c.parsedType.version, c.parsedType.name).impl; @@ -36,12 +37,14 @@ export const ImplWrapperMain = React.forwardRef { + console.log('开始监听 trait 表达式变化', c.id); const stops: ReturnType[] = []; const properties: Array = []; c.traits.forEach((t, i) => { const { result, stop } = stateManager.deepEvalAndWatch( t.properties, ({ result: property }: any) => { + console.log('trait变了', t.type, property); const traitResult = executeTrait(t, property); setTraitResults(oldResults => { // assume traits number and order will not change @@ -101,6 +104,7 @@ export const ImplWrapperMain = React.forwardRef { + console.info('####Component DidMount', c.id); const clearFunctions = propsFromTraits?.componentDidMount?.map(e => e()); return () => { clearFunctions?.forEach(func => func && func()); @@ -109,6 +113,7 @@ export const ImplWrapperMain = React.forwardRef { + console.info('####Component Update', c.id); const clearFunctions = propsFromTraits?.componentDidUpdate?.map(e => e()); return () => { clearFunctions?.forEach(func => func && func()); @@ -116,6 +121,11 @@ export const ImplWrapperMain = React.forwardRef { + console.info( + '####Component DidUnmount', + c.id, + propsFromTraits?.componentDidUnmount + ); propsFromTraits?.componentDidUnmount?.forEach(e => e()); }); diff --git a/packages/runtime/src/components/_internal/ImplWrapper/hooks/useEleMap.tsx b/packages/runtime/src/components/_internal/ImplWrapper/hooks/useEleMap.tsx index 12bab533..8303f025 100644 --- a/packages/runtime/src/components/_internal/ImplWrapper/hooks/useEleMap.tsx +++ b/packages/runtime/src/components/_internal/ImplWrapper/hooks/useEleMap.tsx @@ -15,11 +15,13 @@ export function useEleRef(props: ImplWrapperProps) { }; useEffect(() => { + console.info('####ImplWrapper DidMount', c.id); // If a component is in module, it should not have mask, so we needn't set it if (eleRef.current && !isInModule) { eleMap.set(c.id, eleRef.current); } return () => { + console.info('####ImplWrapper DidUnmount', c.id); if (!isInModule) { eleMap.delete(c.id); } diff --git a/packages/runtime/src/components/_internal/ImplWrapper/hooks/useRuntimeFunctions.ts b/packages/runtime/src/components/_internal/ImplWrapper/hooks/useRuntimeFunctions.ts index b956f8ab..8deaae98 100644 --- a/packages/runtime/src/components/_internal/ImplWrapper/hooks/useRuntimeFunctions.ts +++ b/packages/runtime/src/components/_internal/ImplWrapper/hooks/useRuntimeFunctions.ts @@ -24,6 +24,7 @@ export function useRuntimeFunctions(props: ImplWrapperProps) { const executeTrait = useCallback( (trait: RuntimeTraitSchema, traitProperty: RuntimeTraitSchema['properties']) => { + console.log('执行了trait', trait.type); const tImpl = registry.getTrait( trait.parsedType.version, trait.parsedType.name diff --git a/packages/runtime/src/components/core/Text.tsx b/packages/runtime/src/components/core/Text.tsx index 1e84fa70..4b2cbfcc 100644 --- a/packages/runtime/src/components/core/Text.tsx +++ b/packages/runtime/src/components/core/Text.tsx @@ -37,6 +37,34 @@ export default implementRuntimeComponent({ styleSlots: ['content'], events: [], }, -})(({ value, customStyle, elementRef }) => { - return <_Text value={value} cssStyle={customStyle?.content} ref={elementRef} />; -}); +})( + ({ + value, + customStyle, + elementRef, + // component, + // componentDidMount, + // componentDidUnmount, + // componentDidUpdate, + }) => { + // console.info('####Component Render', component.id); + // useEffect(() => { + // console.info('####Component DidMount', component.id); + // componentDidMount?.forEach(e => e()); + // }, [component.id, componentDidMount]); + // useEffect(() => { + // console.info('####Component Update', component.id); + // componentDidUpdate?.forEach(e => e()); + // }, [component.id, componentDidMount, componentDidUpdate]); + // useEffect(() => { + // return () => { + // console.info('Component DidUnmount', component.id, componentDidUnmount); + // componentDidUnmount?.forEach(e => e()); + // }; + // }, [component.id, componentDidUnmount]); + return <_Text value={value} cssStyle={customStyle?.content} ref={elementRef} />; + } +); + +// 不知道为什么,计时器还在继续,貌似是因为style执行了两次,两个interval,但是clear只执行了一次 +// 另一个问题是,为什么style会执行两次呢? diff --git a/packages/runtime/src/traits/core/Fetch.tsx b/packages/runtime/src/traits/core/Fetch.tsx index 62747ce8..cde595fd 100644 --- a/packages/runtime/src/traits/core/Fetch.tsx +++ b/packages/runtime/src/traits/core/Fetch.tsx @@ -28,6 +28,7 @@ const FetchTraitFactory: TraitImplFactory { + console.log('fetch body', body); if (disabled) return; // TODO: clear when component destroy // FIXME: listen to the header change diff --git a/packages/runtime/src/traits/core/State.tsx b/packages/runtime/src/traits/core/State.tsx index ad0e704d..2c083662 100644 --- a/packages/runtime/src/traits/core/State.tsx +++ b/packages/runtime/src/traits/core/State.tsx @@ -28,6 +28,7 @@ const StateTraitFactory: TraitImplFactory> = () => { props: { componentDidMount: [ () => { + console.log('merge state'); mergeState({ [key]: initialValue }); }, ], diff --git a/packages/runtime/src/traits/core/Style.tsx b/packages/runtime/src/traits/core/Style.tsx index 47bb9967..22308e9a 100644 --- a/packages/runtime/src/traits/core/Style.tsx +++ b/packages/runtime/src/traits/core/Style.tsx @@ -8,9 +8,31 @@ const StyleTraitFactory: TraitImplFactory> = () => { styles.forEach(style => { customStyle[style.styleSlot] = style.style; }); + let interval: ReturnType | undefined; return { props: { customStyle, + componentDidMount: [ + () => { + if (interval) { + clearInterval(interval); + } + interval = setInterval(() => { + console.log(2333, customStyle.content); + }, 1000); + console.log('开始计时', interval); + }, + ], + componentDidUpdate: [], + componentDidUnmount: [ + () => { + console.log('停止计时', interval); + if (interval) { + clearInterval(interval); + interval = undefined; + } + }, + ], }, }; };