這是一篇,引導文吧... 因為寫這篇文章時,實在想不出該如何分序。因此以實現跨域訪問為目的,從基礎知識往上寫。最后以百度搜索智能提示為例,來講解跨域的具體應用!
內容
首先,我們得明確什么是跨域,這里先了解一下url中各組成部分
以百度為例:
https://www.baidu.com:80
協議:https://
二級域名:www
一級域名:baidu.com
端口號:80
以上4個有一個不同即為跨域訪問,比如你當前頁面在https://www.baidu.com:80,你去用Ajax請求https://tieba.baidu.com:80的數據,就相當於跨域訪問!
在Ajax中,是不支持跨域訪問的,所以www.baidu.com拿不到tieba.baidu.com上的數據。
那么這里就要用到跨域訪問的技巧,雖然Ajax不支持,但我們可以利用src這個屬性達到目的。
對於src這個屬性,相信很多人都會想到img標簽!我們都知道img標簽的src如果設置為一個網絡地址時,那么就會去使用該網絡地址的圖片資源。
比如src=https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/bd_logo1_31bdc765.png
那么img標簽就會請求該url的數據返回來,其實這就已經是跨域訪問了。因為你當前的頁面並不在https://ss0.bdstatic.com上,但你卻成功訪問到了它的資源。
因此我們可以利用src這個利器,達到我們跨域訪問的目的。
不過使用src之前,得先了解一下Ajax利用請求回來的響應數據執行回調的一種方法:
//先定義一個函數,等會利用該函數執行回調 function fun (obj) { console.log(obj); } //以下均為ajax請求,粗略看即可 var url = 'test.php';//訪問當前目錄的php文件 var xhr = new XMLHttpRequest(); xhr.open('get',url); xhr.send(); xhr.onreadystatechange = function () { if (xhr.readyState == 4) { if (xhr.status >=200 && xhr.status <300 || xhr.status == 304) { //請求成功后,拿到返回字符串並使用eval執行 eval(xhr.responseText); } else { console.log('請求失敗'); } } }
為了拿到請求數據,下面我們利用php簡單制作一個后端接口test.php
<?php //創建一個php對象 name:kevin,age:23 $obj = array("name"=>"Kevin","age"=>"23"); //將php對象編碼為json格式的字符串 $json = json_encode($obj); //后端給客戶端返回一個字符串 點為字符串拼接(相當於js中加號) echo("fun(" . $json . ")");
請求成功后eval(xhr.responseText);這一句可以一步步分解為如下代碼:
- eval(xhr.responseText);
- eval(fun({"name":"Kevin", "age":"23"}));
- fun({"name":"Kevin", "age":"23"});
- console.log({"name":"Kevin", "age":"23"})
因此控制台打印如下:
以上我們實現了:根據后端返回的數據來決定具體執行某一個函數,並且利用請求回來的數據傳參!
但是以上並沒有解決我們跨域需求,因為我請求的后端接口,依然在當前域!
那么我剛才說了,利用src,我們就能實現跨域。假如我們使用img標簽,使其src="test.php"。這樣我們雖然拿到了數據,但是img標簽並不會像eval函數一樣幫我們執行數據,這樣數據就得不到利用。
所以對於實現跨域,我們有這樣的需求:
- 有src屬性
- 可以像eval函數一樣將數據執行!
滿足以上條件的確實有,那就是script標簽。
平時我們在script標簽內寫代碼,其實寫的就是字符串,並且script標簽會幫我們執行。
並且我們平時經常會用到script標簽的src屬性,比如引入框架時,下面以jQuery為例:<script src="./jquery.js"></script>
其實它就相當於執行了如下:
<script>
//一大堆jQ代碼字符串... </script>
因此我們可以利用script標簽就行跨域訪問,這里以百度為例:
這是百度搜索時,搜索提示的數據接口
https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=關鍵字&cb=方法名
比如我搜索a,頁面如下:
那么我利用接口url也會得到上面數據,如圖:
這里方法名會根據我們的參數返回,因此你請求數據成功后要執行什么函數,那么就往cb傳該函數的方法名!
下面我用盡量少的代碼實現一下 百度搜索提示
<body>
//搜索框
<input type="text" id="input">
//數據請求回來后,往里面添加li
<ul id="ul"></ul>
<script>
//回調方法,數據返回后觸發
function callBack(obj) {
//從上面圖知道關鍵字數組位於數據的s屬性中
var array = obj.s;
//每次觸發先清空以前數據,再添加
ul.innerHTML = "";
for (var i = 0; i < array.length; i++) {
var li = document.createElement('li');
li.innerText = array[i];
ul.appendChild(li);
}
}
//url1 和 url2 為了以后方便拼接
var url1 = 'https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=';
var url2 = '&cb=';
var ul = document.getElementById('ul');
var input = document.getElementById('input');
//監聽輸出框的鍵盤輸入
input.onkeyup = function () {
//創建script標簽
var script = document.createElement('script');
//把輸入框的值和方法名作為url參數
script.src = url1 + this.value+ url2 + callBack.name;
//把script標簽添加到body,那么就會執行代碼
document.body.appendChild(script);
};
</script>
</body>
最后實現效果如下:
代碼僅以實現效果為目的,寫得很簡短,大家可以直接拷貝到自己電腦嘗試~
話題到這里就結束了,web前端學習的可以來我的群,群里每天都有對應資料學習:250777811,歡迎初學和進階中的小伙伴。
如果想看到更加系統的文章和學習方法經驗可以關注的微信號:‘web前端EDU’或者‘webxh5’關注后回復‘2017’可以領取一套完整的學習視頻
