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:'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属性存在的意义
//计算鼠标位移,预防点击事件和拖拽事件冲突
//鼠标按下事件
_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)
});