vue中元素嵌套iframe后绑在父元素上的点击事件失效

vue中元素嵌套iframe后绑在元素上的点击事件失效

问题描述:
在vue项目中,父元素绑定了点击事件,子元素是iframe嵌套的页面,点击iframe页面内不触发点击事件,但是点击其他地方是可以触发点击事件的,如下面格式

1
2
3
<div @click="dosomething">
    &lt;iframex>&lt;/iframex&gt;
</div>

问题分析:
iframe 中加载的是一个相对独立的 Document,如果直接在父页面中给 Document 绑定 click 事件,点击 iframe 并不会触发该事件。

问题解决方案:

1.添加遮罩层
我们可以通过给 iframe 添加一个透明遮罩层,点击 iframe 区域的时候显示透明遮罩层,点击 iframe之外的区域或遮罩层,就关闭遮罩层。但是这种做法存在问题,就是操作不了iframe内的内容

2.给 iframe 的 元素绑定事件

1
&lt;iframex ref="iframe1"  :src="filePath" frameborder="0" scrolling="no" width="100%" height="100%">&lt;/iframex&gt;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 export default {<!-- -->
   data(){<!-- -->
        return{<!-- -->
          mouseE:{<!-- -->
            pageX:'',
            pageY:'',
            isClick: false
          },
          filePath:'https://blog.csdn.net/qq_37656005/article/details/110437769'
    },
    mounted(){<!-- -->
      let _this = this;
      //this.$nextTick等待src里面页面加载完毕,再绑定点击事件
      this.$nextTick(()=>{<!-- -->
        //_this.$refs.iframe1[0].contentWindow 获取iframe对象
       _this.$refs.iframe1[0].contentWindow.onclick = function () {<!-- -->
                  if(_this.mouseE.isClick){<!-- -->
                   //do something
                  }
                }
      })
   
    }
 }

但是这样绑定后,点击事件是可以了,出现了新问题就是点击事件和拖拽事件冲突的问题
解决方案:
判断鼠标是点击事件还是拖拽事件,这就是this.mouseE.isClick属性存在的意义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//计算鼠标位移,预防点击事件和拖拽事件冲突
//鼠标按下事件
_this.$refs.iframe1[0].contentWindow.onmousedown = function (e) {<!-- -->
  //记录当前鼠标位置
  _this.mouseE.pageX = e.pageX;
  _this.mouseE.pageY = e.pageY;
}
//鼠标抬起事件
_this.$refs.iframe1[0].contentWindow.onmouseup = function (e) {<!-- -->
  //计算抬起后鼠标位置和按下位置绝对值是否大于2,是则为拖拽事件,不进行操作,否则为点击事件,进行点击事件操作
  if( 2 < Math.abs(e.pageX -  _this.mouseE.pageX) || 2 < Math.abs(e.pageY -  _this.mouseE.pageY)){<!-- -->
    _this.mouseE.isClick = false;
  }else{<!-- -->
    _this.mouseE.isClick = true;
  }
}

以上就是我想到的解决方案,但这种做法不优雅,而且可能也存在问题
还查到一种是使用 focus-outside 库解决,但是没怎么研究明白,附上git地址,感兴趣的小伙伴可以自行研究
git地址 https://github.com/txs1992/focus-outside/

顺便记录一下iframe和父组件之间的通信问题
还是上述例子

1.在同一个xx.vue页面里使用

1
2
3
4
5
6
7
//iframe页面传递
this.$refs.iframe1[0].contentWindow.postMessage('message','xxx')

//接收在mounted()里
window.addEventListener("message", function(e) {<!-- -->
 console.log(e)
});

2.已知iframe页面,不是第三方页面,是自己本地页面

1
2
3
4
5
6
7
8
9
//在iframe页面里写入
<script>
    window.parent.postMessage('message', '这是传递的信息');
 </script>
 
//接收在mounted()里
window.addEventListener("message", function(e) {<!-- -->
 console.log(e)
});