业务背景
- h5内嵌iframe
- 通过postMessage与web通信
- 其中一个通信约定是:h5页面在初始化;或者任意子组件销毁;或者高度发生变化的时候时候都要向web,send 当前h5下所有组件的相关信息
代码实现
- BaseComponent
用于包裹所有需要与web进行通信的组件 - globalStore
封装了通信函数,此处不做展开
//主要代码
import baseStore from './store';
interface Props {
name: string
children: React.ReactNode;
}
function BaseComponent(props: Props): JSX.Element{
const currentComponent = useRef<any>(null);
useEffect(()=>{
if(!currentComponent.current) return;
const key = Symbol();
baseStore.register(key, currentComponent.current, props.name);
return ()=>{
baseStore.unRegister(key);//组件销毁时,告知web,当前组件销毁,并重新publish所有组件的最新信息
}
}, []);
useEffect(()=>{
if(!currentComponent.current) return;
baseStore.publish();
// 做了一个骨架屏的占位,根据接口重新渲染会产生高度变化;
//或者web的交互导致h5组件发生变化时都要重新发送所有组件的最新信息给web
}, [currentComponent.current ? currentComponent.current.offsetHeight : 0]);
const { currentComponentName } = globalStore
const isCurrentComponent = props.name === currentComponentName
return(
<View
className={'base-component-wrap'}
ref={currentComponent}
>
{props.children}
</View>
)
}
export default observer(BaseComponent);
- baseStore
做组件的依赖收集工作
class Store {
refList: Map<Symbol, any> = new Map([]);
register = (key: Symbol, ref: any, name: string)=>{
this.refList.set(key, {
ref, name
});
this.publish();
}
unRegister = (key:Symbol)=>{
this.refList.delete(key);
this.publish();
}
publish = ()=>{
this.refList.forEach(({ref, name})=>{
globalStore.sendComponentInfo(name, ref);
})
}
}
export default new Store();
小结
代码不难 ,但每一次看似无用的知识储备,被落地在项目里,会有莫名的成就感,时间很仓促,代码总体目前还不够优雅
最后,码字不易 ,如果你有收获,点👍给个鼓励