1. 主页 > 好文章

移动端JS调用iframe方法的3种解决方案(含跨域通信与兼容处理)

你是不是遇到过这种情况?明明在电脑上跑得好好的JS调用iframe代码,一到手机端就各种报错...哎,这时候真想摔手机!别急,今天咱们就聊聊这个让新手抓狂的问题。我敢说,看完这篇,你至少能少加3天班——毕竟当年我为了搞懂这个,差点把键盘都砸了(苦笑)

先问个扎心的问题:为什么你用window.parent.document.getElementById拿不到iframe里的元素?其实啊,这和移动端浏览器内核、安全策略都有关系。下面我要说的这三种方法,保准比你在知乎搜到的"新手如何快速涨粉"那些水文实在多了!

第一种笨办法:直接通信法

最适合刚入门的小白,但有个致命缺点——??只能在同域名下使用??。具体怎么操作呢?

  1. 主页面这样写:

    javascript复制
    let iframe = document.getElementById('myFrame');
    iframe.contentWindow.doSomething(); //直接调用子窗口方法
  2. iframe页面里必须有:

    javascript复制
    function doSomething() {
      alert('成功啦!');
    }

但等等!你可能要问:为什么我在安卓微信浏览器里测试总报错?这就是移动端常见的??跨进程通信阻塞??问题。解决方法很简单——在iframe加载完成后再操作:

javascript复制
iframe.onload = function() {
  //这里才能安全调用
}

第二种黑科技:postMessage跨域

这才是解决跨域问题的正解!不过要注意数据格式,不然就像我当年那样,调试了5个小时发现少了个引号...

??发送方代码??:

javascript复制
//主页面发送
iframe.contentWindow.postMessage('要传递的数据', 'https://目标域名');

//iframe内部发送
window.parent.postMessage('回传数据', '*');

??接收方必须加监听??:

javascript复制
window.addEventListener('message', (e) => {
  if(e.origin !== '信任的域名') return;
  console.log(e.data);
});

这里有个坑爹的地方——安卓7.0以下系统对postMessage的支持有问题。这时候就得用备用方案:

javascript复制
//判断是否支持postMessage
if(typeof window.postMessage === 'undefined') {
  //降级到URL传参方式
  iframe.src += '?data=' + encodeURIComponent(你的数据);
}

第三种野路子:代理页面中转

适合要兼容IE这种古董浏览器的情况。原理就像找中间人传纸条:

步骤分解:

  1. 主页面 => 代理页面(同域)
  2. 代理页面 => 目标iframe(不同域)
  3. 数据通过URL参数传递

不过这种方法有个致命缺陷——??数据量不能超过2KB??!所以最好只传关键参数:

javascript复制
//主页面跳转代理页
location.href = 'proxy.html?action=submit&data=' + data;

//代理页处理
let params = new URLSearchParams(location.search);
iframe.src = 'https://目标域名?action=' + params.get('action');

常见问题答疑

Q:为什么用postMessage有时收不到消息?
A:八成是没校验origin!有次我忘了加校验,结果被恶意网站截胡了数据...

Q:iOS微信里iframe高度异常怎么办?
A:加这个meta标签保命:

html运行复制
name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

Q:移动端滑动穿透怎么破?
A:在iframe外层套个div,加上这个CSS:

css复制
.iframe-wrapper {
  touch-action: none;
  overflow: hidden;
}

表格对比三种方法:

方法跨域支持数据量兼容性
直接通信不支持无限制一般
postMessage支持2MB以内较好
代理页面支持2KB以内极差

小编观点:新手建议先用postMessage练手,等项目上线前再用代理方案兜底。别学我当年非要装逼用高级API,结果上线当天被老板追着骂...(别问我怎么知道的)

本文由嘻道妙招独家原创,未经允许,严禁转载