解决iframe动态切换src后历史记录,导致页面后退变为iframe后退的问题

本文探讨了在Web应用中动态切换iframe src导致的回退问题,即点击回退按钮仅回退iframe而不影响父页面。问题源于动态改变iframe src会产生历史记录条目。解决方法包括使用新的iframe元素替换或利用React和Vue中的key属性强制重新渲染。通过调整key值,可以确保回退操作正确影响整个页面。
摘要由CSDN通过智能技术生成

现象

最近有一个项目内嵌了一个iframe,会在一定条件下动态切换其的src达到切换页面的效果。同时页面父页面中有回退按钮,直接调用的go(-1)。此时就产生了一个奇怪的现象:点击回退按钮,iframe出现了后退,而父页面没有回退。

类似于下面这样:

// 动态切换src
let iframeSrc: string = 'http://example1.com'

setTimeout(() => {
	iframeSrc = 'http://example2.com'
}, 1000)

// vue.js
this.$router.go(-1)

// react.js
history = useHistory()
history.go(-1)

原因

在网上查找了相关资料,原来动态切换iframe的src会导致增加一条iframe的历史浏览记录,无论vue还是react都是基于window.history做路由跳转,所以回退一步就是回退iframe的历史浏览记录。

解决办法

方法一

找到原因后,第一想法就是直接整个替换iframe,于是单独写了一个renderIframe的方法,每次生成一个新的iframe,然而事与愿违。虚拟dom在diff过程中发现只有src变了,于是patch的时候直接更换src,最终回到了最初的起点。

// 写法一
const renderIframe = (src: string) => {
	return <iframe src={src} />
}

因为上面JSX最终调用的React.createElement,还是生成的虚拟节点,遂改成了下面这种写法:

// 写法二
const renderIframe = (src: string) => {
	const iframe = document.createELement('iframe')
	iframe.src = src
	return iframe
}

方法二

巧用key特性,在虚拟dom的diff算法中,key有着超高的地位,如果同一类型的虚拟节点的key不相同,就会直接销毁重新挂载,而没有key区分时就会尽可能的复用打补丁(patch)。根据这个特性,只需在iframe上增加不同的key即可,本人直接使用的src。

// vue.js
<iframe :key="src" :src="src" />

// react.js
<iframe key={src} src={src} />
在使用iframe加载跨域资源时,浏览器会使用同源策略进行限制,因此需要使用代理页面解决跨域问题。ASP.NET中可以使用aspx页面来作为代理页面。 具体步骤如下: 1. 在项目中添加一个aspx页面,例如Proxy.aspx。 2. 在Proxy.aspx.cs文件中编写一个处理请求的方法,例如GetResource()。 3. 在GetResource()方法中使用WebRequest对象向目标资源发起请求,并获取响应数据。 4. 将响应数据返回给前端页面。 5. 在前端页面中使用iframesrc属性指定代理页面的地址,并将目标资源的地址作为参数传递给代理页面。 6. 在代理页面中获取目标资源的地址,并在GetResource()方法中使用该地址发起请求。 7. 将响应数据返回给前端页面,并在前端页面中使用iframe加载响应数据。 示例代码如下: Proxy.aspx.cs: ```csharp protected void Page_Load(object sender, EventArgs e) { // 获取目标资源的地址 string url = Request.QueryString["url"]; // 发起请求并获取响应数据 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); HttpWebResponse response = (HttpWebResponse)request.GetResponse(); StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8); string data = reader.ReadToEnd(); // 将响应数据返回给前端页面 Response.Clear(); Response.Write(data); Response.End(); } public void GetResource(string url) { // 构造代理页面的地址 string proxyUrl = "http://localhost:8080/Proxy.aspx?url=" + url; // 使用iframe加载代理页面 var iframe = document.createElement("iframe"); iframe.src = proxyUrl; document.body.appendChild(iframe); } ``` 前端页面: ```html <body> <script> GetResource("https://example.com/resource"); </script> </body> ```
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值