[toc]
## previously
在ajax請求中如果協議和端口號和當前的一樣,那么是可以省略的
```
var xhr = new XMLHttpRequest;
xhr.open("get","data.txt",true); //注意不要加'/',加了'/'是從根目錄開始找
xhr.onreadystatechange = function(){
if(xhr.readyState ===4 && xhr.status ==200){
console.log(xhr.responseText);
}
};
xhr.send(null);
```
## 什么是JSONP
JSONP和AJAX相同,都是客戶端向服務器端發送請求,給服務器端傳遞內容 或則 從服務器端獲取內容 的方式。
### JSONP 和 AJAX 的區別
AJAX屬于同源策略
JSONP屬于非同源策略(跨域請求),實現跨域請求的方式有很多種,只不過JSONP是最常用的。
### 區分同源和非同源
1)協議
2)域名或則IP
3)端口號
以上三部分完全相同屬于同源策略,我們使用AJAX技術獲取數據;只要有一個不一樣,就屬于非同源,我們一般使用JSONP獲取數據
### webstorm測試支持
WB(webstorm)在預覽頁面的時候會默認的創建一個本地虛擬的服務,端口號是63342
## 原理
JSONP利用了script標簽不管是否是同源還是非同源
在script的世界中,沒有同源跨域這一說,只要你給我src屬性中的地址就是一個合法的地址,script都可以把對應的內容請求回來
JSON就是利用了SCRIPT的這個原理
1)我們首先把需要請求數據的那個跨域的API數據接口的地址賦值給SCRIPT的SRC
2)把當前頁面中的某一個函數名當做參數值傳遞給跨域請求數據的服務器(URL問號傳參,一般是:?callback=fn)
3)服務器接收到你的請求后,需要進行特殊的處理,把你傳遞進來的函數名和它需要給你的數據拼接成一個字符串 例如:我們傳遞進去的函數名是fn,它準備好的數據是`fn({"name":"ahhh"})`->`我傳遞的函數名(需要給我們的數據)`
4)最后服務器把準備的數據以HTTP協議的形式返回給我們客戶端,客戶端發現其實就是讓我們的fn執行,而且還給fn傳遞了一堆的數據,那些數據就是我們想要的
**So,如果對方服務器不支持的話,JSONP也無用**
```
<scirpt src="js/index.js"></script> //同源
<script src="http://ping.js.qq.com/ping.js"></script>
```
```
<script>
function(data){
console.log(data);
}
</script>
<script src="http://xxx?callback=fn"></script>
```


返回的是`fn({...})`,也就是讓函數執行了

### 服務端配合

## jQueryのJSONP
```
$.ajax({
url:"data.txt"
,type:"get"
,dataType:"json"
,data:null
,async:true
,cache:false
,timeout:1000 //->超時,走error,一般設定為3000ms
,success:function(data){
console.log(data)
}
,error:function(){
}
})
```
jQuery會幫我把數據抽離出來
```
$.ajax({
url:""
// ,type:"get"
,dataType:"jsonp"
,success:function(data){
console.log(data);
}
})
```

會自動生成隨即,防止cache

另外JSONP都是GET&&異步請求的
也可以定義傳遞給服務器的函數名和形參名
```
$.ajax({
...
jsonpCallback:"fn" //把函數名變為fn,原本是jquery+隨即字符串
,jsonp:"cb" //把傳遞函數名的那個形參callback變為cb
})
```

## 百度搜索案例
suggestion su?wd=


鏈接地址格式 s?word=

>**注意:** ajax封裝的jsonp方法,success中的data直接就是我們想要的數據而不是拼接后的整個函數。
blur會先click而觸發,這樣的話就獲取不到click到的那個li的內容,so應該用事件委托

```
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>百度模糊搜索-珠峰培訓</title>
<style type="text/css">
* {
margin: 0;
padding: 0;
font-family: "\5FAE\8F6F\96C5\9ED1", Helvetica, sans-serif;
font-size: 14px;
color: #424242;
}
ul, li {
list-style: none;
}
input {
display: block;
outline: none;
}
html, body {
width: 100%;
height: 100%;
}
.search {
margin: 20px auto;
width: 300px;
}
.search input {
padding: 0 5px;
width: 288px;
height: 35px;
border: 1px solid green;
}
.searchList {
display: none;
width: 298px;
border: 1px solid green;
border-top: none;
}
.searchList li {
padding-left: 5px;
height: 35px;
line-height: 35px;
cursor: pointer;
}
.searchList li:hover {
background: #eee;
}
</style>
</head>
<body>
<div class="search">
<input type="text" id="searchInput"/>
<ul class="searchList">
</ul>
</div>
<script type="text/javascript" src="js/jquery-1.11.3.min.js"></script>
<script type="text/javascript">
$(function () {
var $searchInput = $("#searchInput"),
$search = $(".search"),
$searchList = $search.children(".searchList");
//->光標進入文本框(或者是用戶在輸入的過程中),通過判斷是否存在內容來控制列表區域的顯示隱藏
$searchInput.on("focus keyup", function () {
var val = $(this).val().replace(/^ +| +$/g, "");
if (val.length > 0) {
showList();
return;
}
$searchList.stop().slideUp(200);
});
//->事件委托:點擊的時候,如果事件源是文本框我們什么操作都不做處理,如果事件源是LI,我們讓LI中的內容進入到文本框中,并且讓列表區隱藏,如果事件源是其它的操作我們都要隱藏
$("body").on("click", function (e) {
var tar = e.target, $tar = $(tar);
if (tar.id === "searchInput") {
return;
}
if (tar.tagName.toUpperCase() === "LI" && $tar.parent().hasClass("searchList")) {
$searchList.stop().slideUp(200);
$searchInput.val($tar.html());
return;
}
$searchList.stop().slideUp(200);
});
//->根據輸入內容的不一樣,我們的列表區域顯示不一樣的內容
function showList() {
var val = $searchInput.val().replace(/^ +| +$/g, "");
//->如果文本框中不存在內容的話,我們不需要在獲取列表信息了
if (val.length === 0) {
return;
}
//->通過JSONP跨域請求把我們輸入內容所匹配回來的數據獲取到
$.ajax({
url: "https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=" + val,
type: "get",
dataType: "jsonp",
jsonp: "cb",
success: function (data) {
var str = '';
if (data && data["s"]) {
data = data["s"];
$.each(data, function (index, item) {
if (index <= 3) {
str += '<li>' + item + '</li>';
}
});
}
if (!str) {//->如果獲取的數據一個都沒有的話,我們直接的隱藏列表即可
$searchList.css("display", "none");
return;
}
$searchList.html(str).stop().slideDown(200);
}
});
}
});
</script>
</body>
</html>
```
## 其他跨域解決方案
### Access-Control-Allow-Origin

`*`代表所有

### 通過自身的后端代理
這說明了是瀏覽器器自身限制了跨域的請求


## 還有那些標簽可以跨域
- link
- img
- script
## 關于script標簽
不關心script中src的后綴名是什么,只要請求回來的東西能被js引擎解析即可(會被解析成js代碼)
```
<script src="./test.txt"></script>
```
相當于

如果返回的數據不符合js解析語法會報錯

- 空白目錄
- window
- location
- history
- DOM
- 什么是DOM
- JS盒子模型
- 13個核心屬性
- DOM優化
- 回流與重繪
- 未整理
- 文檔碎片
- DOM映射機制
- DOM庫封裝
- 事件
- 功能組件
- table
- 圖片延遲加載
- 跑馬燈
- 回到頂部
- 選項卡
- 鼠標跟隨
- 放大鏡
- 搜索
- 多級菜單
- 拖拽
- 瀑布流
- 數據類型的核心操作原理
- 變量提升
- 閉包(scope)
- this
- 練習題
- 各種數據類型下的常用方法
- JSON
- 數組
- object
- oop
- 單例模式
- 高級單例模式
- JS中常用的內置類
- 基于面向對象創建數據值
- 原型和原型鏈
- 可枚舉和不可枚舉
- Object.create
- 繼承的六種方式
- ES6下一代js標準
- babel
- 箭頭函數
- 對象
- es6勉強筆記
- 流程控制
- switch
- Ajax
- eval和()括號表達式
- 異常信息捕獲
- 邏輯與和或以及前后自增
- JS中的異步編程思想
- 上云
- 優化技巧
- 跨域與JSONP
- 其它跨域相關問題
- console
- HTML、XHTML、XML
- jQuery
- zepto
- 方法重寫和方法重載
- 移動端
- 響應式布局開發基礎
- 項目一:創意簡歷