注意:此文章方法仅适用于h5项目(同域名下,非同域名请使用跨域通讯达到目的)
近期在一个一个新h5(uni-app)项目中需要使用webview(iframe)引用一个老项目,并对老项目的页面作出干涉以添加新功能因此需要获取到其dom对象来获取信息和操作页面
一、首先需要解决第一个问题,获取到本页面的iframe对象,这时候可能你会奇怪,本页面的iframe对象
//iframe.length - 1 这样写是因为我这个webview是一个公共组件
//有几个tabbar页面也引用了,会导致页面里会有好几个iframe
//经过我反复尝试当前显示的永远会在末尾
window.document.getElementsByTagName("iframe")[iframe.length - 1]
一下不就有了吗?确实是这样的,但是在uni-app项目里这却是一个大坑。
1.在uniapp项目中,webview在渲染初期如下获取iframe标签对象的代码及其不稳定,成功获取到iframe标签的概率就像碰运气,这时候你会可能问为啥不等一会再获取呢?
太天真了,这里面的玄学你根本把握不住,
我因为需要实时获取应用页面状态所以在每次webview内部url地址变更后我都会循环操作40次,每0..5s一次,iframe标签就像鬼一样时有时无,太刺激了。所以这个项目前期功能异常不稳定,对引用页的操作失败率奇高。后来研究了很久,不知何时灵光一闪想到了一个很好的解决办法
let dom = window.document.getElementsByTagName("body")[0]
let iframe = dom.getElementsByTagName("iframe")
iframe = iframe[iframe.length - 1]
这样写iframe对象的获取成功率基本是加载完成就能获取到项目依仗这个办法运行异常平稳。
2.最近有新功能加入,所以我又把项目拿出来改,改来改去发现了一个突然新增的问题,我都要疯了,这个问题有可能是我以前没发现也有可能是后续改动造成的影响。就是当你在某个webview页停留几分钟(或者在应用内,这个我没试,因为可以复现问题,尝试)那么
window.document.getElementsByTagName("body")
方法会返回 undefined ,没错body竟然没有了,玄学吧。那您猜怎么着,这个时候我们最开始放弃的方法又可以非常准确的获取到iframe对象了,加倍的玄学,我说啊,写代码跟修仙似的,
所以最终把两者结合一下得到了一个非常稳定的获取webview dom对象的方法
let dom = window.document.getElementsByTagName("body")[0]
if(!dom){
dom = window.document
}
let iframe = dom.getElementsByTagName("iframe")
iframe = iframe[iframe.length - 1]
try {
if (iframe) {
iframe = iframe.contentWindow
}
}catch (e) {
//TODO handle the exception
}
用这个新方法可以写一个监听webview地址变化的方法作为示例(我是懒得想其他办法,200毫秒虽然不算太快但是满足项目需求也就无所谓了)
checkWebHref() {
let dom = window.document.getElementsByTagName("body")[0]
if(!dom){
dom = window.document
}
let iframe = dom.getElementsByTagName("iframe")
iframe = iframe[iframe.length - 1]
try {
if (iframe) {
iframe = iframe.contentWindow
if (iframe.document && iframe.document.location && iframe.document.location.href){
//获得ifram当前地址,至于监听,赋值给data对象使用watch监听就可以了
console.log(iframe.document.location.href)
}
}
}catch (e) {
//TODO handle the exception
}
//定时递归以达到监听目的
setTimeout(() => {
this.checkWebHref()
}, 200)
}
各位大佬轻踩,笨人笨法,主要是解决问题
在此记录增加记忆