全部編程語言都離不開的三大數據結構javascript
scalar 標量:數字和字符串html
sequence 序列:數組和列表java
mapping 映射:鍵值對ajax
JSON:JavaScript Object Notation,輕量級的數據交互格式正則表達式
JSON 數據是沒有方法的普通對象,或者是包含這種對象的數組編程
var person = {
"name": "jett",
"age": "22",
"sex": "男"
}
var persons = [
{
"name": "jett",
"age": "22",
"sex": "男"
},
{
"name": "lily",
"age": "20",
"sex": "女"
}
]
複製代碼
[]
包圍JSON 轉換成 JS 對象json
JSON.parse()跨域
<div id='box' data-info='{"name":"Jett","age":"22"}'></div>
複製代碼
// JSON.parse(str) str -> object
var box = document.getElementById('box');
var jsonData = box.getAttribute('data-info');
var obj = JSON.parse(jsonData);
console.log(obj);
// {name:"Jett",age:"22"}
複製代碼
eval()數組
var obj = eval('('+jsonData+')');
// eval 能夠執行任何 JS 代碼,因此能夠將 jsonData 看成代碼執行
// 爲安全性考慮,最好使用 JSON.parse()
複製代碼
JS 對象轉換 JSON瀏覽器
JSON.stringify()
var obj = {
name: 'Jett',
age: 22,
sex: '男'
}
var jsonData = JSON.stringify(obj);
console.log(jsonData);
// {"name":"Jett","age":22,"sex":"男"}
複製代碼
AJAX:Asynchronous JavaScript and XML,異步的 JavaScript 和 XML
AJAX 不是新的編程語言,而是一種使用現有標準的新方法
AJAX 最大的優勢是在不從新加載整個頁面的狀況下,能夠與服務器交換數據並更新部分網頁內容
AJAX 工做原理
瀏覽器建立 XMLHttpRequest 對象,發送 AJAX 請求
服務器接收請求,建立響應,返回數據
瀏覽器接收數據,動態渲染頁面
建立 XMLHttpRequest 對象
XMLHttpRequest 用於在後臺與服務器交換數據
兼容 IE7 及以上
var xmlhttp;
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
} else {
// 兼容 IE6/5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
複製代碼
發送 AJAX 請求
GET 請求
url 爲請求地址,在地址後使用 ?
拼接消息內容,如 ?name=Jett&age=22
xmlhttp.open('GET',url, true);
xmlhttp.send();
複製代碼
POST 請求
send 方法內傳入消息內容,如:name=Jett&age=22
xmlhttp.open('POST',url, true);
// xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
// 經過 setRequestHeader 設置請求頭
xmlhttp.send(data);
複製代碼
GET 請求比 POST 更快,但安全性低,且傳輸數據的大小有限制
第三參數 true 表明異步,fasle 表明同步
監聽響應狀態
XMLHttpRequest 對象有 readystatechange 事件,用於監聽 readystate 的改變
XMLHttpRequest 對象的 readystate 表示 AJAX 請求的狀態
0: 請求未初始化
1: 服務器鏈接已創建
2: 請求已接收
3: 請求處理中
4: 請求已完成,且響應已就緒
複製代碼
XMLHttpRequest 對象的 status 表示 http 請求的狀態碼
200: 請求
404: 未找到頁面
複製代碼
監聽 readystatachange 事件,並判斷狀態
當 xmlhttp.readyState 爲 4,xmlhttp.status 爲 200 時,表明請求成功且響應就緒
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4 && xmlhttp.status==200) {
// ...
}
}
複製代碼
處理響應
XMLHttpRequest 對象的 responseText 或 responseXML 屬性用於接收服務端返回的數據
顧名思義,respnseXML 用於接收 XML 格式的響應數據,responseText 用於接收通常數據
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4 && xmlhttp.status==200) {
console.log(xmlhttp.responseText);
// 得到響應數據並使用
}
}
複製代碼
跨域請求
URL = 協議名 + 主機名 + 端口號 + 資源名稱
域 = 協議名 + 主機名 + 端口號
出於安全性考慮,只有當頁面所在域和請求的目的地址在同一域才容許訪問
JSONP 是一種跨域解決方案
目前解決瀏覽器跨域問題的方法有 JSONP、cors 策略等,cors 策略是 HTML5 的新特性,老版本瀏覽器可能不支持,JSONP 是最經常使用的處理方式
在 HTML 衆多標籤中,有些標籤具備跨域功能,如 script、img、iframe
JSONP 就是利用 script 標籤的跨域能力,動態生成一個 script 標籤,指定 src 爲請求地址
頁面中定義的方法
<scrip type="text/javascript">
funtion test(data) {
console.log(data);
}
</scrip>
<!--動態生成的 script 標籤-->
<script type="text/javascript" src="htpp://localhost:8888"></script>
複製代碼
htpp://localhost:8888 地址返回的數據
test('這是請求返回的數據')
複製代碼
將生成的 script 標籤添加到 DOM 中,瀏覽器根據 src 請求目的地址,獲得返回的數據,由於是 script 標籤,瀏覽器會將返回的數據當成 JS 代碼來執行,就是執行頁面中定義的方法,恰好能夠將其中的參數順利帶到頁面中
咱們在頁面上定義一個函數,將其函數名經過 URL 查詢字符串傳到服務端,服務端拼接字符串,返回執行該函數的 JS 代碼,並將要傳遞的數據放在參數中,這樣在頁面上定義好的函數就能夠被執行,而且獲得了服務端傳來的數據,在該函數內執行成功回調,就能夠對服務端數據進行處理了
對於普通 AJAX 請求咱們能夠經過監聽 XMLHttpRequest 的 readystatechange 事件,判斷 readystate 和 status 來知曉請求和響應是否完成,以執行成功回調或出錯回調
JSONP 方式本質上是利用 script 標籤的 src 進行請求,響應狀況以下:
若是 src 指向資源存在,且其返回的字符串被當成 JS 代碼成功執行
即頁面內定義好的函數被成功執行,該函數內的成功回調函數能夠經過參數拿到數據進行處理
若是 src 指向的目的資源訪問不到
script 標籤會觸發 error 事件,監聽此事件能夠得到執行出錯回調的時機
var script = document.createElement('script');
script.onerror = funtion() {
// 執行出錯回調函數
}
複製代碼
若是 src 指向資源存在,返回的字符串會由於是 script 標籤而被執行,執行過程當中出錯
在執行成功回調函數前,對 script 標籤對象添加一個標記屬性,監聽 script 的 load 事件發生時對象是否有該標籤屬性
由於 onload 函數在 script 標籤加載完成後執行,script 標籤在其引入的代碼執行後,纔會響應 onload 處理函數,經過判斷標記屬性是否添加成功,能夠知曉 script 標籤引入的代碼是否成功執行,若是標記屬性爲 undefined,則執行出錯回調
若是觸發 error 事件,onerror 事件處理函數將執行,但 onload 將不執行,由於目標資源訪問出錯,並無加載完成
var script = document.createElement('script');
window.callback = function (res) {
script['jsonp'] = 1;
// 執行成功回調函數
}
script.onload = function () {
if (typeof script['jsonp'] === 'undefined') {
// 執行出錯回調函數
}
}
複製代碼
須要注意的是,IE8 及如下 script 標籤對象不支持 onerror,也不支持 onload,但支持 onreadystatechange
經過判斷 readystate 來知曉 script 標籤的加載狀態,當 readystate 爲 loaded 或 complete 時,表示 script 標籤加載完成,即 script 標籤引入的代碼已經執行,一樣的,在成功回調函數前爲 script 對象添加標記屬性,經過判斷標記屬性是否添加成功,能夠知曉 script 標籤引入的代碼是否成功執行,若是標記屬性爲 undefined,則執行出錯回調
script.onreadystatechange = function () {
// 正則表達式判斷 readystate 是否爲 loaded 或 complete
if (/loaded|complete/i.test(this.readyState)) {
if (typeof script['jsonp'] === 'undefined') {
// 執行出錯回調函數
}
}
}}
複製代碼
函數名動態生成,利用 onload 配合 onreadystate 判斷加載狀態,執行完畢後 delete 對應函數,並 remove 對應 script 標籤節點
在本身封裝 JSONP 函數時,咱們可能會在 window 對象下動態添加函數如 callback,這樣 script 的 src 指定資源返回形如 callback('數據') 的字符串數據,就能夠直接執行此函數並獲取數據,可是咱們在優化 JSONP 函數時,會但願將動態建立的函數刪除,在 IE8 中 delete window 下的屬性會報不支持,咱們能夠在 Window.prototype 上添加函數,一樣能夠在直接執行,且支持 delete
封裝一個 ajax 函數,支持 get、post、jsonp 三種形式的請求,以對象形式傳入參數
配置項
var opt = {
type: 'get',
url: 'http://...',
data: { // 數據使用對象形式
name: 'zzh',
age: '21'
},
async: true, // 默認 true
success: function(res) {
},
error: function() {
},
timeout: 3000 // 默認 60000
}
複製代碼
代碼
function ajax(option) {
// 設置默認參數
var opt = {
type: option.type.toUpperCase(),
url: option.url,
data: option.data || null,
async: option.async || false,
success: option.success,
error: option.error,
timeout: option.timeout || 60000
};
// 用於 jsonp 的回調函數名
var callback = 'callback' + new Date().getTime();
var type = opt.type,
success = opt.success,
error = opt.error,
data = parseData(opt.data); // 將 data 對象裝換成查詢字符串
if (type === 'GET' || type === 'POST') {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
success && success(xhr.responseText, xhr.status);
} else {
error && error(xhr.status);
}
}
if (type == 'GET') {
opt.url += data;
data = null;
}
xhr.open(type, opt.url, opt.async);
xhr.send(data);
setTimeout(function () {
xhr.abort();
console.error(opt.url + '請求超時');
}, opt.timeout);
} else if (type === 'JSONP') {
var script = document.createElement('script');
script.src = opt.url + data;
// 選則存放在 Window 原型上,window 下能夠使用
// 若是直接存放在 window 上,IE8 window 屬性不支持 dalete
Window.prototype[callback] = function (res) {
script['jsonp'] = 1;
success && success(res);
}
document.body.appendChild(script);
// -[1,] 在 IE8 返回 NaN,IE9 及以上返回 -1
if (-[1,]) {
// IE9 及以上支持 onerror
// onerror 用於請求失敗,未執行 callback
// onload 用於請求成功,但執行 callback 出錯
script.onerror = script.onload = function () {
if (typeof script['jsonp'] === 'undefined') {
error && error();
}
script.parentNode.removeChild(script);
delete Window.prototype[callback];
}
} else {
// script.onreadystatechange 兼容 IE8
script.onreadystatechange = function () {
// -[1,] 在 IE8 返回 NaN,IE9 及以上返回 -1
if (/loaded|complete/i.test(this.readyState)) {
if (typeof script['jsonp'] === 'undefined') {
error && error();
}
script.parentNode.removeChild(script);
delete Window.prototype[callback];
}
}
}
}
function parseData(data) {
var arr = [],
str;
if (type === 'GET') {
str = '?';
} else if (type === 'POST') {
str = '';
} else if (type === 'JSONP') {
str = '?callback=' + callback + '&';
}
for (var k in data) {
arr.push(k + '=' + data[k]);
}
return str + arr.join('&');
}
}
// 使用示例
ajax({
type: 'jsonp',
url: 'http://127.0.0.1:8888/',
data: {
name: 'jett',
age: 22
},
success: function (res) {
console.log('接收數據:' + res);
},
error: function () {
console.log('error() 執行了');
}
})
複製代碼