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

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

<div @click="dosomething">
    <iframe></iframe>
</div>

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

问题解决方案:

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

2.给 iframe 的 元素绑定事件

<iframe ref="iframe1"  :src="filePath" frameborder="0" scrolling="no" width="100%" height="100%"></iframe>
export default {
   data(){
        return{
          mouseE:{
            pageX:'',
            pageY:'',
            isClick: false
          },
          filePath:''
    },
    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属性存在的意义

//计算鼠标位移,预防点击事件和拖拽事件冲突
//鼠标按下事件
_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页面里使用

//iframe页面传递
this.$refs.iframe1[0].contentWindow.postMessage('message','xxx')

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

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

//在iframe页面里写入
<script>
    window.parent.postMessage('message', '这是传递的信息');
 </script>
 
//接收在mounted()里
window.addEventListener("message", function(e) {
 console.log(e)
});