iframe 内部的 focus 事件导致 tabs 组件显示错误

背景:

vue 项目,使用的 iview 组件库,tabs 组件,每个 tab 下有个 iframe,不跨域。
我想要实现 iframe 的预加载,在第一个 iframe onload 之后加载第二个。

遇到的问题:

本来预加载第二个 iframe 的时候第二个该隐藏的,还是显示第一个,但是由于 iframe 内部执行了 focus 事件导致聚焦的元素跑到了屏幕中心,tab 显示错位。此时获取 iframe 的 dom 元素,并执行 contentWindow.blur() 之后并不能使 tab 回到正确的位置。请问有没有办法可以阻止 iframe 执行 focus 事件?

有其他思路的同学欢迎提出不同想法~谢谢

阅读 5k
1 个回答

找到解决方法了,写给后来人。

我们在执行focus事件的时候其实还可以传一个参数的:

ele.focus({ preventScroll: false })

preventScroll:一个布尔值。如果是 true 的话,在视口外部的元素获得焦点之后不会自动滚动到视口中。如果是 false,则元素获得焦点后会自动滚动到视口中。默认情况下,直接调用focus()等于focus({ preventScroll: false })

所以想让页面正常显示,有两个方法:

  1. 获取焦点时传参,不让页面滚动;
  2. 监听滚动事件,发生滚动时让元素再滚回去。

因为我们项目内部嵌套的 iframe 不是自己项目的,所以只能监听scroll事件了,但是一般情况下focus事件的scroll是监听不到的,参考这个回答:stackoverflow.

// 想要监听 focus 的 scroll,addEventListener 需要传第三个参数
window.addEventListener('scroll', function(e){...}, true)

所以最终的解决方案:

// iframe 子组件
created () {
  window.addEventListener('scroll', function (e) {
    if (e.target.className === 'tableauWrapTabSty ivu-tabs') {
      // console.dir(e.target)
      e.target.scrollLeft = 0
    }
  }, true)
},
destroyed () {
  window.removeEventListener('scroll', function (e) {
    console.dir(e.target)
  })
}

参考:

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题