js - iframe更改src后,浏览器后退只能后退iframe,不能使父页面后退解决办法

js - iframe更改src后,浏览器后退只能后退iframe,不能使父页面后退解决办法

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

<template>
  <div class="iframe-box">
    <iframe :key="url" class="iframe" :src="url"></iframe>
  </div>
</template>
<script>
import ENV from '@/constant/env'
export default {
  data () {
    return {
      path: `${ENV.mdm}`,
      url: ''
    }
  },
  watch: {
    $route (to, from) {
      this.setUrl()
    }
  },
  created () {
    this.setUrl()
  },
  destroyed () {
    window.removeEventListener('message', this.postMessageFunc)
  },
  mounted () {
    window.addEventListener('message', this.postMessageFunc)
  },

  methods: {
    setUrl () {
      this.url = `${ENV.mdm}${window.location.pathname}${window.location.search}`
    },
    postMessageFunc (e) {
      console.log(e, '接收的数据')
      if (e.data === 'goBack') {
        window.removeEventListener('message', this.postMessageFun)
        this.$router.go(-1)
      } else if (e.data === 'workbenchApproval') {
        this.$router.push('/workbench/my-approval')
      } else if (e.data === 'workbenchApplication') {
        this.$router.push('/workbench/my-application')
      }
      // let arr = [
      //   'http://mdm-dev.didichuxing.com',
      //   'http://mdm-test.didichuxing.com',
      //   'http://mdm-stage.didichuxing.com',
      //   'http://mdm.didichuxing.com',
      // ];
      // // 跳转地址
      // let pathUrl = {
      //   draft: '/task/draft',
      //   submitted: '/task/submitted',
      //   home: '/home',
      //   todo: '/task/todo',
      //   done: '/task/done',
      //   notified: '/task/notify',
      // };
      // 来源判断
      // if (arr.includes(e.origin)) {
      //   if (e.data === 'goBack') {
      //     window.removeEventListener('message', this.postMessageFun);
      //     this.$router.go(-1);
      //   } else {
      //     window.removeEventListener('message', this.postMessageFun);
      //     // this.$router.push({
      //     //   path: `${pathUrl[e.data]}`,
      //     //   query: {
      //     //     source: 'supplier'
      //     //   }
      //     // })
      //   }
      // }
    }
  }
}
</script>

<style lang="less" scoped>
.iframe-box {
  width: 100%;
  height: 100%;
}
.iframe {
  width: 100%;
  height: inherit;
  border: none;
}
</style>

重置iframe的高度函数

function setIframeHeight () {
				  	//初始不执行
				    try {
				        vm.timer;
	                } catch (e) {
	                    return;
	                }
	                
				    var ifm = document.getElementById("main");
				    ifm.height = 0;
			        
			        var iframeWin = ifm.contentWindow || ifm.contentDocument.parentWindow;
			        vm.timer = setInterval(function () { //开启定时器
				        if (iframeWin.document.body && iframeWin.$ && iframeWin.$("#dpLTE").length > 0) {
				            var ifmHeight = iframeWin.$("#dpLTE").height(); //iframe高度
				            //var ifmHeight = iframeWin.document.documentElement.scrollHeight || iframeWin.document.body.scrollHeight; //iframe高度
				            
				            ifm.height = ifmHeight;
				            iframeWin.$("body").css("overflow", "hidden"); //超出隐藏
				            iframeWin.$(".content-fluid").css("padding", "0"); //消除边距
					        //window.clearInterval(vm.timer); //清除定时器
			            }
			        }, 200);
				}

类似于下面这样:

解法一

找到原因后,第一想法就是直接整个替换iframe,于是单独写了一个renderIframe的方法,每次生成一个新的iframe,然而事与愿违。虚拟dom在diff过程中发现只有src变了,于是patch的时候直接更换src,最终回到了最初的起点。
浏览器的机制如此,在iframe导航变化后手动点击浏览器的后退按钮也依然只是后退iframe中的导航。

有一种解决方案是不要修改iframe.src,而是删除旧iframe元素,新建一个iframe元素并替换它,这样不会产生history。

直接createElement,替换原来的iframe。

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

解法二

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

<iframe id="main" name="main" ref="iframe" frameborder="0" width="100%" scrolling="auto" v-if="reloadIframe" :src="iframeUrl" @load="setIframeHeight()">


 methods: {
    view: function() {
        // 先让iframe销毁
        var that = this;
        that.reloadIframe = false;
        that.$nextTick(function() {
            // 赋值地址,再加载
            that.iframeUrl = url;
            that.reloadIframe = true;
        })
    }
}

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

解法三 使用document.referrer,可以获取前一页面的URL地址的方法

function back() { window.location.href = window.document.referrer; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值