You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

仅Safari出现:Vue组件中Iframe加载SSO时隔次打开新tab问题

问题根因
  • 该问题是Safari浏览器特有的DOM节点缓存机制导致的:组件卸载时,Safari不会主动清理iframe的name属性全局注册记录,当组件二次挂载时,新的iframe和旧的残留记录重名,表单提交时无法正确匹配到当前页面的iframe target,就会默认触发新标签页打开行为,第三次挂载时旧的残留记录刚好被GC回收,所以表现为隔一次复现的规律。
  • 异步获取SSO信息后调用$nextTick的时机在Safari下无法100%保证iframe已经完成挂载渲染,也会加重target匹配失败的概率。
修复方案

修改后的完整代码如下:

<template>
  <div>
  <form
    :action="endPoint"
    :target="iframeName"
    ref="ssoForm"
    method="POST"
    name="ssoForm"
    id="ssoForm"
  >
    <input
      id="AuthCode"
      type="hidden"
      name="AuthCode"
      :value="authorizationCode"
    />
    <input
      id="AuthAppUrl"
      type="hidden"
      name="AuthAppUrl"
      :value="authAppUrl"
    /> 
    
  </form>
  <iframe
      width="100%"
      :name="iframeName"
      height="300"
      style="display: flex"
      :id="iframeName"
      frameborder="0"
      ref="ssoIframe"
    ></iframe>
  </div> 
</template>

<script>
import types from "path/to/types"
export default {
  data() {
    return {
      endPoint: null,
      authorizationCode: null,
      authAppUrl: null,
      errorStatus: false,
      error: null,
      // 每次挂载生成唯一的iframe name,避免和残留记录重名
      iframeName: `the_iframe_${Date.now()}_${Math.random().toString(36).slice(2)}`
    }
  },
  methods: {
    async getSSOModel() {
      try {
        var data = await this.$store.dispatch(
          `store/${types.GET_SSO_MODEL}`
        )
        this.endPoint = data.endPoint
        this.authorizationCode = data.authorizationCode
        this.authAppUrl = data.authAppUrl 
        await this.$nextTick()
        // 提交前主动确认iframe节点已存在
        if (this.$refs.ssoIframe && this.$refs.ssoForm) {
          this.$refs.ssoForm.submit()
        }
      } catch (error) { 
        this.error = error
        this.errorStatus = true
      }
    }
  },
  async mounted() {
    await this.getSSOModel()
  },
  beforeUnmount() {
    // 组件卸载前主动清理iframe内容,避免Safari缓存残留
    if (this.$refs.ssoIframe) {
      this.$refs.ssoIframe.src = 'about:blank'
      this.$refs.ssoIframe.remove()
    }
    if (this.$refs.ssoForm) {
      this.$refs.ssoForm.remove()
    }
  }
}
</script>
修复逻辑说明
  • 每次组件挂载时生成唯一的iframe name值,彻底避开Safari的同名target缓存问题
  • 增加生命周期钩子主动销毁iframe和表单节点,清空iframe内容,主动触发Safari的缓存清理
  • 提交表单前增加节点存在校验,避免异步逻辑导致的节点未挂载就提交的问题
  • 如果使用Vue2开发,将代码中的beforeUnmount生命周期钩子替换为beforeDestroy即可生效

内容的提问来源于stack exchange,提问作者Jim's Code Corner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 09:54:06