儘管iframe因兼容、性能等問題逐漸被替換掉,但有不少存量項目仍在使用。最近,我們部門一位小夥伴遇到iframe跨域相關問題,詳細如下:
[問題前置條件]
- 有兩個系統A、B(都是銀行存量老系統),A、B跨域;
- A系統中有一個頁面a、B系統中有一個頁面b;
- b以iframe方式嵌在a頁面中。
[問題描述]
- 原來的邏輯是:在b頁面有一個保存按鈕,點擊“保存” -> 將b頁面的數據存在B系統,a頁面處理完成後調用B系統的接口,把b頁面的數據再通過接口的方式傳給A系統。
- 現在優化的邏輯是:在b頁面有一個保存按鈕,點擊“保存” -> b頁面調用a頁面的方法,將數據傳過去,直接保存。
那麼,iframe、跨域、如何通信?
[解決方法]
方法一:通過代理頁面通信
父頁面http://localhost:8081/dlParent.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>利用代理頁面解決iframe跨域問題</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script type="text/javascript">
function excute(url){
$("#test2").attr("src", url);
}
</script>
</head>
<body>
<h1>父頁面</h1>
<iframe id="test1" src="http://127.0.0.1:8080/dlChild.html" width="100%" height="100px"></iframe>
<iframe id="test2" src="" width="100%" height="500px"></iframe>
</body>
</html>
代理頁面http://localhost:8081/iframe.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<SCRIPT type="text/javascript">
window.onload = function(){
try{
top.excute(getQueryString("url"));
}catch(e){
if(getQueryString("errorTime") == null){
location.href = "http://127.0.0.1:8081/iframe.html?errorTime=1&url=" + escape(getQueryString("url"));
}else if(getQueryString("errorTime") === "1"){
location.href = "http://localhost:8081/iframe.html?errorTime=2&url=" + escape(getQueryString("url"));
}
}
}
function getQueryString(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
var r = window.location.search.substr(1).match(reg);
if (r != null) return unescape(r[2]);
return null;
}
</SCRIPT>
</head>
<body>
</body>
</html>
子頁面http://localhost:8080/dlChild.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Insert title here</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script>
function turn(){
var url = $("#url").val();
crossFrame("http://localhost:8081/iframe.html?url=" + escape(url));
}
function crossFrame(url){
if(!$("#crossFrame").length > 0) {
var iframe = document.createElement("iframe");
iframe.setAttribute("style", "position:absolute; top:-9999px; left:-9999px");
iframe.setAttribute("src", url);
iframe.setAttribute("id", "crossFrame");
document.body.appendChild(iframe);
}else{
$("#crossFrame").attr("src",url);
}
}
</script>
</head>
<body>
<h3>子頁面</h3>
<input id="url" type="input" value="http://www.baidu.com" style="width:400px;"/>
<input type="button" value="保存" onclick="turn()"/>
</body>
</html>
頁面效果如下:
方法二:postMessage
父頁面 http://localhost:8081/pmParent.html
<!DOCTYPE html>
<html>
<head>
<title>window.postMessage</title>
<meta charset="utf-8"/>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
</head>
<body>
<h1 class="header">page parent</h1>
<div class="mb20">
<textarea name="ta" id="data" cols="30" rows="5">Hi,I'm father</textarea>
<button style="font-size:20px;" onclick="javascript:send()">處理</button>
</div>
<!-- 跨域的情況 -->
<iframe src="http://localhost:8080/pmChild.html" id="child" style="display: block; border: 1px dashed #ccc; height: 300px;"></iframe>
</body>
<script type="text/javascript">
window.addEventListener('message', function(messageEvent) {
var data = messageEvent.data;
$("#data").text("from child: " + data)
//保存數據到A系統
}, false);
</script>
</html>
子頁面http://localhost:8080/pmChild.html:
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8"/>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
</head>
<body>
<h1 class="header">page child</h1>
<input type="text" id="inp" value="耶啵~咔滋咔滋">
<button onclick="send()">保存</button>
</body>
<script type="text/javascript">
function send() {
var data = document.querySelector('#inp').value;
//爲保證各瀏覽器兼容性,可用JSON.stringify()方法對data進行序列化,data可以是複合對象
parent.postMessage(data, 'http://localhost:8081/pmParent.html');
}
</script>
</html>
頁面運行效果如下: