Solid-JS多屏应用中如何让iframe保留跳转后的页面状态?
解决SolidJS多屏应用中iframe保留浏览历史的问题
问题根源
切换到其他屏幕时,包含iframe的组件会被SolidJS卸载,再次返回时组件重新挂载,iframe会重新加载初始src地址,导致之前的跳转状态丢失。
解决方案
1. 用状态保存iframe当前URL
监听iframe的load事件,实时保存当前页面地址,组件重新挂载时用保存的URL作为src。
示例代码:
import { createSignal } from 'solid-js'; function IframeScreen() { const [currentUrl, setCurrentUrl] = createSignal("https://gkwhelps.herokuapp.com"); const handleIframeLoad = (e) => { // 仅同源页面可获取contentWindow.location,跨域场景会被浏览器拦截 if (e.target.contentWindow?.location) { setCurrentUrl(e.target.contentWindow.location.href); } }; return ( <iframe width="100%" height="1300" id="myiframe" src={currentUrl()} onLoad={handleIframeLoad} ></iframe> ); }
注意:如果iframe内嵌跨域网站,浏览器同源策略会阻止你获取内部页面的URL,这种情况优先用下面的方案。
2. 避免组件卸载(保留iframe DOM)
不要完全卸载iframe所在组件,改用CSS的display: none隐藏,切换屏幕时仅控制显示/隐藏,这样iframe的会话状态会被浏览器保留。
示例代码:
import { createSignal } from 'solid-js'; function App() { const [activeScreen, setActiveScreen] = createSignal("iframe"); return ( <div> <button onClick={() => setActiveScreen("iframe")}>切换到iframe屏</button> <button onClick={() => setActiveScreen("other")}>切换到其他屏</button> <div style={{ display: activeScreen() === "iframe" ? "block" : "none" }}> <iframe width="100%" height="1300" id="myiframe" src="https://gkwhelps.herokuapp.com" ></iframe> </div> <div style={{ display: activeScreen() === "other" ? "block" : "none" }}> <h1>其他屏幕内容</h1> </div> </div> ); }
3. 用SolidJS <Show> 组件的keepAlive属性(SolidJS 1.6+)
SolidJS 1.6及以上版本的<Show>组件支持keepAlive,设置为true会保留组件DOM不卸载,自然保留iframe状态。
示例代码:
import { createSignal, Show } from 'solid-js'; function App() { const [showIframe, setShowIframe] = createSignal(true); return ( <div> <button onClick={() => setShowIframe(true)}>显示iframe屏</button> <button onClick={() => setShowIframe(false)}>显示其他屏</button> <Show when={showIframe()} keepAlive={true}> <iframe width="100%" height="1300" id="myiframe" src="https://gkwhelps.herokuapp.com" ></iframe> </Show> <Show when={!showIframe()} keepAlive={true}> <h1>其他屏幕内容</h1> </Show> </div> ); }
跨域场景提示
如果iframe内嵌的是跨域网站,无法获取内部页面URL,优先使用避免组件卸载的方案(方案2或3),完全依赖浏览器保留iframe的会话状态即可。
内容的提问来源于stack exchange,提问作者gks
相关产品推荐
相关产品推荐

