diff --git a/src/components/Playground/Output/Preview/Render.tsx b/src/components/Playground/Output/Preview/Render.tsx new file mode 100644 index 0000000..940a80f --- /dev/null +++ b/src/components/Playground/Output/Preview/Render.tsx @@ -0,0 +1,77 @@ +import iframeRaw from '@/components/Playground/Output/Preview/iframe.html?raw' + +interface RenderProps { + iframeKey: string + compiledCode: string + onError?: (errorMsg: string) => void +} + +interface IMessage { + type: 'LOADED' | 'ERROR' | 'UPDATE' | 'DONE' + msg: string + data: { + compiledCode: string + } +} + +const getIframeUrl = (iframeRaw: string) => { + const shimsUrl = '//unpkg.com/es-module-shims/dist/es-module-shims.js' + // 判断浏览器是否支持esm ,不支持esm就引入es-module-shims + const newIframeRaw = + typeof import.meta === 'undefined' + ? iframeRaw.replace( + '', + `` + ) + : iframeRaw + return URL.createObjectURL(new Blob([newIframeRaw], { type: 'text/html' })) +} + +const iframeUrl = getIframeUrl(iframeRaw) + +const Render = ({ iframeKey, compiledCode, onError }: RenderProps) => { + const iframeRef = useRef(null) + const [loaded, setLoaded] = useState(false) + + const handleMessage = ({ data }: { data: IMessage }) => { + const { type, msg } = data + switch (type) { + case 'LOADED': + setLoaded(true) + break + case 'ERROR': + onError?.(msg) + break + case 'DONE': + onError?.('') + } + } + + useEffect(() => { + window.addEventListener('message', handleMessage) + + return () => { + window.removeEventListener('message', handleMessage) + } + }, []) + + useEffect(() => { + if (loaded) { + iframeRef.current?.contentWindow?.postMessage({ + type: 'UPDATE', + data: { compiledCode } + } as IMessage) + } + }, [compiledCode, loaded]) + + return ( +