去年,在給導師做項目時需要解決一個跨域問題,當時沒弄過,就從網上找了資料給解決了,時至今日讓我再提怎麼做的,早已忘掉。再有就是以前聽過jsonp,但是對此概念全然不知,只覺得跟json只差一個p。直到前幾天帶我的師傅跟我說了下jsonp,然後又自己查看了jsonp的原理後,才知道jsonp是怎麼一回事。爲了以後自己可以快速拾起這些知識,在這裏粗略記錄一下。
iframe跨域
1.遇到的問題
我們的頁面A.html
別人的頁面B.html(兩個頁面不同域)
A.html要嵌套B.html頁面,而且被嵌套的B.html頁面需要調用A.html的js方法
思想:
在a.html同一個域下創建一個c.html,就是利用c.html這個頁面來作爲b.html頁面訪問a.html頁面js方法的橋樑
通過在a.html中嵌套b.html,然後在嵌套在a中的b.html頁面中再(有點繞,仔細體會)動態創建一個iframe,把c.html頁面嵌套進去,然後b.html便可以通過動態嵌套的c.html頁面來調用a.html的js方法了。
隨便畫了張圖,表示下嵌套的層次:
實現:
直接上代碼比較清楚:(ip跟域名來說不是在同一個域下,所以可以用一臺機子中ip127.0.0.1與localhost來模擬)
localhost:8080/test1/a.html代碼
<html>
<head>
<title>無標題文檔</title>
</head>
<body>
<iframe src="http://127.0.0.1:8080/test2/b.html" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" name="myframe"></iframe>
<script>
function test(data)
{
alert("這個是a中的方法,參數:"+data);
}
</script>
</body>
</html>
這段代碼中嵌套了b.html頁面,然後,我們的目的是點擊b.html頁面中按鈕可以調用a.html頁面中的test方法。
localhost:8080/test1/c.html代碼 (c.html頁面與a.html頁面在同一個域中,實驗中與a.html頁面同一目錄下了)
<html>
<head>
<meta charset="utf-8">
<title></title>
<script>
window.onload = function(){
var text = window.location.href.split('=')[1]
parent.parent.test(text);
}
</script>
</head>
<body>
</body>
</html>
c.html頁面中沒有什麼代碼,就是爲了b.html頁面調用此頁面的時候,幫助調用a.html中的方法。
c調用a的方法的時候用了 parent.parent.方法名來調用的,因爲c是作爲a底下兩層嵌套。
127.0.0.1:8080/test2/b.html代碼
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>跨域測試</title>
</head>
<body>
<ul>
<li>測試</li>
</ul>
<input type="button" onclick="exec_iframe()" value="調用a頁面方法"></input>
<script>
function exec_iframe(){ //此方法就是動態創建iframe,然後將c.html頁面嵌套進來
var text = "abcddddddd";
if(typeof(exec_obj)=='undefined'){
exec_obj = document.createElement('iframe');
exec_obj.name = 'tmp_frame';
exec_obj.src = 'http://localhost:8080/test1/c.html?content='+text;
exec_obj.style.display = 'none';
document.body.appendChild(exec_obj);
}else{
exec_obj.src = 'http://localhost:8080/test1/c.html?content='+text;
}
}
</script>
</body>
</html>
當點擊b中的按鈕時,會調用方法exec_iframe() ,然後動態將c頁面嵌套進來,c頁面初始化便會調用其頁面中的js方法,便實現了調用a頁面中的test方法。
----------------------------------------------------------------------------------------------------------------
總結下流程:
啓動tomcat,訪問a.html頁面
b頁面中的內容便加載進來了,在b.html中有文本以及一個按鈕,然後點擊按鈕,去調用a.html中的方法,這個過程就是上面說的,在b中動態嵌入c頁面,然後由c頁面來調用a中的方法。(參數沒有轉碼,沒什麼影響)
同理,如果想在a中調用b中的方法的話,那可以在b.html同目錄下或者說同域下創建一個頁面d,d中調用b中的方法(parent.window.myframe.方法名,此處的myframe是b在a頁面中的iframe名稱),當a也調用b中方法的時候,同樣在頁面中動態創建一個iframe來嵌套d頁面。
jsonp簡談
以我自己的理解,jsonp不是什麼協議,更不是什麼數據格式,只是幫助獲取外域數據的一種方法。
這種方法就是利用了瀏覽器對<script src ="http://.............." ></script>不採取“同源策略”的特點來實現數據獲取的。
當我們使用src時,是可以調用別的站點的資源,舉例來說:
a.html頁面中有段js
<script>
function test()
{
alert("通過遠程資源文件調用我啊");
}
</script>
<script src="http://xxxxx/remote.js"></script>
遠程的這個remote.js文件的內容是:
test();
那當a頁面加載時會彈出彈框。
其實,這就是jsonp的依賴的原理,src指向的不止是一個js文件,同樣可以是一個請求地址:
src="http://xxxx/xxxx/getcount?callback=test"(callback就是一個普通參數名,完全可以換成別的,只要跟後臺約定好就ok了)
這樣的話我們可以在後臺方法getcount中拿到參數callback,這個callback參數是幹嘛的呢,就是向後臺說明你從後臺拿到數據後,要用哪個方法來處理,也就是讓後臺給你返回像上面test()方法這樣的東西。
給個完整例子就是:
<script>
function dealcount(data)
{
alert("獲取後臺數據:"+data);
//拿到數據,處理數據
}
</script>
<script src="http://xxxx/xxxx/getcount?callback=dealcount"></script></span>
當這個頁面加載的時候便回去請求這個鏈接,後臺拿到參數test,以及經過後臺處理好的數據data,然後返回來 dealcount(data),那麼這個是不是就跟remote.js中寫個dealcount(data)一樣了,就會執行自己頁面上寫的dealcount(data)方法了。
但是這個例子是個靜態的,不能每次都是頁面加載的時候來請求吧。要需要時再去請求,那就寫個方法去動態生成script標籤,然後動態加載到頁面中吧。
function jsonpRequest(){
var url = "http://xxxx/xxxx/getcount?callback=dealcount";</span>
//創建script標籤,設置其屬性
var script = document.createElement('script');
script.setAttribute('src', url);
//把script標籤加入head,此時調用開始
document.getElementsByTagName('head')[0].appendChild(script);
}
jsonp在jquery中也可以使用ajax的方式,只要知道了這個jsonp是個什麼東西,那麼ajax中的使用也就是一看便明瞭 了。
如果有別的跨域以及這方面的知識,可以推薦給我,謝謝!
-------------------- 等回頭看看自己,寫的又傻又笨的時候,那麼說明我成長了!