这里记录日常工作中遇到的一些问题,便于日后查看,每解决一个问题,都是一次进步。
1. 获取iframe 中的元素
一开始的做法是通过普通的方法来实现,结果打印的一直都是 null,就查询原因,了解到了 iframe中元素不能用普通的方式获取。
错误的写法
<iframe id="demo_iframe" :src="src">
<div id="area-code">
...这是内容
</div>
</iframe>
<script>
const el = document.querySelector('#area_code')
console.log('get dom', el) // null
</script>
正确做法: 需要先获取 iframe元素, 通过 iframe 的 contenwidth 对象来获取 iframe中的dom元素。
<iframe id="demo_iframe" :src="src">
<div id="area-code">
...这是内容
</div>
</iframe>
<script>
const iframe = document.getElementById('demo_iframe').contentWindow;
const el = iframe.document.querySelector('#area-code')
console.log('get dom', el) // 此时有值 <div id="area_code">...</div>
</script>
2. iframe中的通信问题
组件 dome.vue 中 存在 iframe; 组件 areaCode.vue 是 iframe中的结构; 需要:自己模拟的一个下拉选择框的效果,现在想要实现,点击下拉框之外的区域,下拉区域收起。
错误的做法 在 areaCode.vue 中监听 mouseDown 事件,关闭下拉框,发现当点击 areaCode.vue 组件之外的区域, 就监听不到 mouseDown 事件了。
<script>
export default {
// areaCode.vue
mounted() {
window.addEventListener('mousedown', this.clickDom)
},
destroyed() {
window.removeEventListener('mousedown', this.clickDom)
},
methods: {
clickDom() {
console.log('click out')
this.visible = false
}
},
}
</script>
然后以为是因为区域的问题,将监听的方法放在了 dome.vue 中,发现还是不行。 然后又 通过 eventBus,发现也不行。
向大佬请求帮助, 可以通过 postMessage 来进行 iframe的通信。 同时在维护的另一个项目中已经有使用了,参考着实现了需求。
最终的做法
// demo.vue 中
export default {
mounted() {
window.addEventListener('mousedown', this.clickDom)
},
destroyed() {
window.removeEventListener('mousedown', this.clickDom)
},
methods: {
clickDom() {
const iframe = document.querySelector('#demo_iframe')
// 给 iframe页面发送消息
iframe.contentWindow.postMessage('click-dom');
}
},
};
// areaCode.vue 中, 监听 message 事件, 接收参数
export default {
mounted() {
window.addEventListener('message', this.clickDom)
},
methods: {
clickDom(e) {
console.log('=====', e)
if(e.data === 'click-dom' && this.visible) {
this.visible = false
}
}
},
};
关于 iframe 的 通信,还可以反过来通信, message 事件的参数也有好几个值,更多具体细节可查看MDN
===== 待续 =====