vue中元素嵌套iframe后绑在元素上的点击事件失效
问题描述:
在vue项目中,父元素绑定了点击事件,子元素是iframe嵌套的页面,点击iframe页面内不触发点击事件,但是点击其他地方是可以触发点击事件的,如下面格式
1 2 3 | <div @click="dosomething"> <iframex></iframex> </div> |
问题分析:
iframe 中加载的是一个相对独立的 Document,如果直接在父页面中给 Document 绑定 click 事件,点击 iframe 并不会触发该事件。
问题解决方案:
1.添加遮罩层
我们可以通过给 iframe 添加一个透明遮罩层,点击 iframe 区域的时候显示透明遮罩层,点击 iframe之外的区域或遮罩层,就关闭遮罩层。但是这种做法存在问题,就是操作不了iframe内的内容
2.给 iframe 的 元素绑定事件
1 | <iframex ref="iframe1" :src="filePath" frameborder="0" scrolling="no" width="100%" height="100%"></iframex> |
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) }); |