* JSON 使用 JavaScript 語法來描述數(shù)據(jù)對象,但是 JSON 仍然獨立于語言和平臺。JSON 解析器和 JSON 庫支持許多不同的編程語言。
合格的json對象:
["one", "two", "three"]
{ "one": 1, "two": 2, "three": 3 }
{"names": ["張三", "李四"] }
[ { "name": "張三"}, {"name": "李四"} ]
不合格的json對象:
{ name: "張三", 'age': 32 } // 屬性名必須使用雙引號
[32, 64, 128, 0xFFF] // 不能使用十六進制值
{ "name": "張三", "age": undefined } // 不能使用undefined
{ "name": "張三",
"birthday": new Date('Fri, 26 Aug 2011 07:13:10 GMT'),
"getName": function() {return this.name;} // 不能使用函數(shù)和日期對象
}
JavaScript中關于JSON對象和字符串轉換的兩個方法:
JSON.parse(): 用于將一個 JSON 字符串轉換為 JavaScript 對象
JSON.parse('{"name":"run1"}');
JSON.parse('{name:"run1"}') ; // 錯誤
JSON.parse('[18,undefined]') ; // 錯誤
JSON.stringify(): 用于將 JavaScript 值轉換為 JSON 字符串。
JSON.stringify({"name":"run1"})
JSON 格式于2001年由 Douglas Crockford 提出,目的就是取代繁瑣笨重的 XML 格式。
JSON 格式有兩個顯著的優(yōu)點:書寫簡單,一目了然;符合 JavaScript 原生語法,可以由解釋引擎直接處理,不用另外添加解析代碼。所以,JSON迅速被接受,已經成為各大網(wǎng)站交換數(shù)據(jù)的標準格式,并被寫入ECMAScript 5,成為標準的一部分。
XML和JSON都使用結構化方法來標記數(shù)據(jù),下面來做一個簡單的比較。
用XML表示中國部分省市數(shù)據(jù)如下:
<?xml version="1.0" encoding="utf-8"?>
<country>
<name>中國</name>
<province>
<name>黑龍江</name>
<cities>
<city>哈爾濱</city>
<city>大慶</city>
</cities>
</province>
<province>
<name>廣東</name>
<cities>
<city>廣州</city>
<city>深圳</city>
<city>珠海</city>
</cities>
</province>
<province>
<name>臺灣</name>
<cities>
<city>臺北</city>
<city>高雄</city>
</cities>
</province>
<province>
<name>新疆</name>
<cities>
<city>烏魯木齊</city>
</cities>
</province>
</country>
用JSON表示如下
{
"name": "中國",
"province": [{
"name": "黑龍江",
"cities": {
"city": ["哈爾濱", "大慶"]
}
}, {
"name": "廣東",
"cities": {
"city": ["廣州", "深圳", "珠海"]
}
}, {
"name": "臺灣",
"cities": {
"city": ["臺北", "高雄"]
}
}, {
"name": "新疆",
"cities": {
"city": ["烏魯木齊"]
}
}]
}
由上面的兩段代碼可以看出,JSON 簡單的語法格式和清晰的層次結構明顯要比 XML 容易閱讀,并且在數(shù)據(jù)交換方面,由于 JSON 所使用的字符要比 XML 少得多,可以大大得節(jié)約傳輸數(shù)據(jù)所占用的帶寬。
AJAX(Asynchronous Javascript And XML)翻譯成中文就是“異步Javascript和XML”。即使用Javascript語言與服務器進行異步交互,傳輸?shù)臄?shù)據(jù)為XML(當然,傳輸?shù)臄?shù)據(jù)不只是XML)。
AJAX除了異步的特點外,還有一個就是:瀏覽器頁面局部刷新;(這一特點給用戶的感受是在不知不覺中完成請求和響應過程)
示例:
頁面輸入兩個整數(shù),通過AJAX傳輸?shù)胶蠖擞嬎愠鼋Y果并返回。
HTML部分代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="x-ua-compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>AJAX局部刷新實例</title>
</head>
<body>
<input type="text" id="i1">+
<input type="text" id="i2">=<input type="text" id="i3">
<input type="button" value="AJAX提交" id="b1">
<script src="/static/jquery-3.2.1.min.js"></script>
<script>
$("#b1").on("click", function () {
$.ajax({
url:"/ajax_add/",
type:"GET",
data:{"i1":$("#i1").val(),"i2":$("#i2").val()},
success:function (data) {
$("#i3").val(data);
}
})
})
</script>
</body>
</html>
views.py
def ajax_demo1(request):
return render(request, "ajax_demo1.html")
def ajax_add(request):
i1=int(request.GET.get("i1"))
i2=int(request.GET.get("i2"))
ret=i1 + i2
return JsonResponse(ret, safe=False)
urls.py
urlpatterns=[
...
url(r'^ajax_add/', views.ajax_add),
url(r'^ajax_demo1/', views.ajax_demo1),
...
]
$.ajax({
url:"", // 控制往哪里提交
type:"POST", // 請求的方法
data:{}, // 請求的參數(shù)
success:function(arg){
// 收到響應之后要做的事
}
})
搜索引擎根據(jù)用戶輸入的關鍵字,自動提示檢索關鍵字。
還有一個很重要的應用場景就是注冊時候的用戶名的查重。
其實這里就使用了AJAX技術!當文件框發(fā)生了輸入變化時,使用AJAX技術向服務器發(fā)送一個請求,然后服務器會把查詢到的結果響應給瀏覽器,最后再把后端返回的結果展示出來。
當輸入用戶名后,把光標移動到其他表單項上時,瀏覽器會使用AJAX技術向服務器發(fā)出請求,服務器會查詢名為lemontree7777777的用戶是否存在,最終服務器返回true表示名為lemontree7777777的用戶已經存在了,瀏覽器在得到結果后顯示“用戶名已被注冊!”。
優(yōu)點
最基本的jQuery發(fā)送AJAX請求示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="x-ua-compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ajax test</title>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<button id="ajaxTest">AJAX 測試</button>
<script>
$("#ajaxTest").click(function () {
$.ajax({
url: "/ajax_test/",
type: "POST",
data: {username: "Q1mi", password: 123456},
success: function (data) {
alert(data)
}
})
})
</script>
</body>
</html>
views.py
def ajax_test(request):
user_name=request.POST.get("username")
password=request.POST.get("password")
print(user_name, password)
return HttpResponse("OK")
$.ajax參數(shù)
data參數(shù)中的鍵值對,如果值值不為字符串,需要將其轉換成字符串類型。
$("#b1").on("click", function () {
$.ajax({
url:"/ajax_add/",
type:"GET",
data:{"i1":$("#i1").val(),"i2":$("#i2").val(),"hehe": JSON.stringify([1, 2, 3])},
success:function (data) {
$("#i3").val(data);
}
})
})
方式1
通過獲取隱藏的input標簽中的csrfmiddlewaretoken值,放置在data中發(fā)送。
$.ajax({
url: "/cookie_ajax/",
type: "POST",
data: {
"username": "rum2",
"password": 123456,
"csrfmiddlewaretoken": $("[name='csrfmiddlewaretoken']").val() // 使用JQuery取出csrfmiddlewaretoken的值,拼接到data中
},
success: function (data) {
console.log(data);
}
})
通過獲取返回的cookie中的字符串 放置在請求頭中發(fā)送。
注意:需要引入一個jquery.cookie.js插件。
$.ajax({
url: "/cookie_ajax/",
type: "POST",
headers: {"X-CSRFToken": $.cookie('csrftoken')}, // 從Cookie取csrf_token,并設置ajax請求頭
data: {"username": "rum", "password": 123456},
success: function (data) {
console.log(data);
}
})
或者用自己寫一個getCookie方法:
function getCookie(name) {
var cookieValue=null;
if (document.cookie && document.cookie !=='') {
var cookies=document.cookie.split(';');
for (var i=0; i < cookies.length; i++) {
var cookie=jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1)===(name + '=')) {
cookieValue=decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken=getCookie('csrftoken');
每一次都這么寫太麻煩了,可以使用$.ajaxSetup()方法為ajax請求統(tǒng)一設置。
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
Django內置的serializers
def books_json(request):
book_list=models.Book.objects.all()[0:10]
from django.core import serializers
ret=serializers.serialize("json", book_list)
return HttpResponse(ret)
我們的數(shù)據(jù)中經常有日期時間,也就是datetime對象,而json.dumps是無法處理這樣在類型的,那就需要通過自定義處理器來做擴展,如下:
class JsonCustomEncoder(json.JSONEncoder):
"""
自定義一個支持序列化時間格式的類
"""
def default(self, o):
if isinstance(o, datetime):
return o.strftime("%Y-%m-%d %H:%M:%S")
elif isinstance(o, date):
return o.strftime("%Y-%m-%d")
else:
return json.JSONEncoder.default(self, o)
def books_json(request):
book_list=models.Book.objects.all().values_list("title", "publish_date")
ret=json.dumps(list(book_list), cls=JsonCustomEncoder)
return HttpResponse(ret)
Bootstrap-sweetalert
https://github.com/lipis/bootstrap-sweetalert
$(".btn-danger").on("click", function () {
swal({
title: "你確定要刪除嗎?",
text: "刪除可就找不回來了哦!",
type: "warning",
showCancelButton: true,
confirmButtonClass: "btn-danger",
confirmButtonText: "刪除",
cancelButtonText: "取消",
closeOnConfirm: false
},
function () {
var deleteId=$(this).parent().parent().attr("data_id");
$.ajax({
url: "/delete_book/",
type: "post",
data: {"id": deleteId},
success: function (data) {
if (data.status===1) {
swal("刪除成功!", "你可以準備跑路了!", "success");
} else {
swal("刪除失敗", "你可以再嘗試一下!", "error")
}
}
})
});
})
#科技##軟件開發(fā)##python#
山代有人才出,各領風騷數(shù)百年。
Hello,大家好,我是編程三昧的作者隱逸王,小小前端一枚。
自昨天發(fā)了《還在死磕 Ajax?那可就 out 了!》一文后,收到了一些大家的一些評論,評論都很走心,也很有深度。
說實話,雖然我在盡可能努力地回復大家的問題,但還是避免不了對其中一些概念理解的模棱兩可的情況,有幸得到同仁們的指點,比如:
感謝各位的不吝賜教,讓我在成長的道路上又前進了幾分。
現(xiàn)在總結一下,評論區(qū)涉及到的主要問題如下:
為了不辜負大家的熱情,我在這里試著解釋一下這些問題,如有疏漏,還請海涵!
首先,我們來了解一下 Ajax、Axios 和 Fetch 它們各自的概念。
英文全稱為 Asynchronous JavaScript + XML ,翻譯過來就是異步JavaScript和XML。
它是用來描述一種使用現(xiàn)有技術集合的“新”方法的,這里的“新”方法主要涉及到: HTML 或 XHTML、CSS、 JavaScript、DOM、XML、XSLT,以及最重要的 XMLHttpRequest。
當使用結合了這些技術的 AJAX 模型以后, 網(wǎng)頁應用能夠快速地將增量更新呈現(xiàn)在用戶界面上,而不需要重載(刷新)整個頁面。這使得程序能夠更快地回應用戶的操作。
Ajax 是一個概念模型,是一個囊括了眾多現(xiàn)有技術的集合,并不具體代指某項技術。
Ajax 最重要的特性就是可以局部刷新頁面。
Axios 是一個基于 Promise 網(wǎng)絡請求庫,作用于 Node.js 和瀏覽器中。 它是 isomorphic 的(即同一套代碼可以運行在瀏覽器和 Node.js中)。在服務端它使用原生 Node.js http 模塊,而在客戶端則使用 XMLHttpRequest。
這里我們只關注客戶端的 Axios,它是基于 XHR 進行二次封裝形成的工具庫。
客戶端 Axios 的主要特性有:
Fetch 提供了一個獲取資源的接口(包括跨域請求)。
Fetch 是一個現(xiàn)代的概念, 等同于 XMLHttpRequest。它提供了許多與 XMLHttpRequest 相同的功能,但被設計成更具可擴展性和高效性。
Fetch 的核心在于對 HTTP 接口的抽象,包括 Request、Response、Headers 和 Body,以及用于初始化異步請求的 global fetch。得益于 JavaScript 實現(xiàn)的這些抽象好的 HTTP 模塊,其他接口能夠很方便的使用這些功能。
除此之外,F(xiàn)etch 還利用到了請求的異步特性——它是基于 Promise 的。
fetch() 方法必須接受一個參數(shù)——資源的路徑。無論請求成功與否,它都返回一個 Promise 對象,resolve 對應請求的 Response。
通過上面對三者概念的解釋,我們應該大體清楚它們之間的關系了,我在這里用圖表示一下:
針對上圖,我解釋一下:
其實這個問題更準確的問法應該是:Fetch 真的會取代傳統(tǒng) Ajax ( XHR ) 嗎?
要回答這個問題,我們需要清楚以下幾點:
基于以上幾點,我的觀點是Fetch 終會取代傳統(tǒng) Ajax,但過程可能比較漫長。
雖然目前來看,傳統(tǒng) Ajax (比如 Axios 之類的)在使用規(guī)模上遠遠超過 Fetch,但要知道,這是 XHR 十來年累積下來的效果。
封裝得到的 Axios 在易用性上甩了原生 XHR 十萬八千里,但畢竟是封裝的,和原生的 Fetch 相比較,Axios 在出身上就已略輸一籌,且原生的 API 天然上會支持更多的功能,使用上會更加靈活。
在昨天文章的評論區(qū),有一位同學推薦了一個 Fetch 工具庫,名為 Mande,有興趣的同學可以去看看。
以上就是針對 Fetch 和 Ajax 問題的一份簡單解釋,希望能夠給大家?guī)韱l(fā)。
就我個人而言,倒是蠻期待 Fetch 能夠取代傳統(tǒng) Ajax,技術的發(fā)展需要不斷注入活力才行,我還能再干幾十年,可不希望前端技術裹足不前,那樣該多無聊 !
~
~本文完,感謝閱讀!
~
學習有趣的知識,結識有趣的朋友,塑造有趣的靈魂!
大家好,我是〖編程三昧〗的作者 隱逸王,我的公眾號是『編程三昧』,歡迎關注,希望大家多多指教!
你來,懷揣期望,我有墨香相迎! 你歸,無論得失,唯以余韻相贈!
知識與技能并重,內力和外功兼修,理論和實踐兩手都要抓、兩手都要硬!
var xhr = new ?XMLHttpRequest();
調用的第一個方法是open()
xhr.open(method,url,false)
注:
1、如果url不是絕對路徑,那么就是相對于當前頁面。
2、open語句并不會立刻發(fā)送請求,需要send()方法。
3、只能向同一個域中使用相同端口和協(xié)議的URL發(fā)送請求。
要發(fā)送請求,需要再使用send方法:
xhr.send(null)
send方法的參數(shù)是指要發(fā)送的數(shù)據(jù),如果沒有的話需要寫null。一般get方式不傳數(shù)據(jù),post方法需要傳送數(shù)據(jù)。
xhr收到響應后,會有下面這些屬性:
接到響應后,首先檢查status,確定是否成功返回:
1、200響應成功;
2、304請求的資源沒有被修改,可使用緩存內容;
可使用下面的代碼檢測響應狀態(tài):
xhr.open("get", "example.txt", false);
xhr.send(null);
if ((xhr.status >=200 && xhr.status < 300) || xhr.status ==304) {
alert(xhr.responseText);
} else {
alert("Request was unsuccessful: " + xhr.status);
}
發(fā)送異步請求時,需要監(jiān)控readyState屬性,該屬性有如下幾個值:
每次readyState的值變化一次,就會觸發(fā)一次readystatechange事件,所以可以在這個事件來檢查readyState的值。
xhr.onreadystatechange = function () {
if (xhr.readyState ==4){
if ((xhr.status >=200 && xhr.status < 300) || xhr.status ==304){
alert(xhr.responseText);
} else{
alert("Request was unsuccessful" + xhr.status);
}
}
};
由于并不是所有瀏覽器都支持DOM2,所以采用DOM0級的方法來添加事件處理程序。
頭部信息有以下內容:
在open()方法之后,send()方法之前,通過調用setRequestHeader()可設置請求頭:
xhr.setRequestHeader("Host","https://www.baidu.com");
使用getResponseHeader(“Host”)可以相應的值;
使用getAllResponseHeaders()可以得到一個包含所有頭部信息的長字符串。
var myHeader= xhr.getResponseHeader("Host");
var allHeaders= xhr.getAllResponseHeaders();
GET請求是將查詢字符串經過編碼(encodeURIComponent)后拼接到URL后面的。
下面的函數(shù)的作用是將查詢字符串經過編碼后拼接到URL后面:
// 對查詢參數(shù)進行編碼并拼接
function addURLParam(url,name,value) {
url +=(url.indexOf("?")==-1 ? "?" : "&");
url += encodeURIComponent(name) + "=" + encodeURIComponent(value);
}
那么完整的請求如下:
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState ==4){
if ((xhr.status >=200 && xhr.status < 300) || xhr.status ==304){
var myHeader= xhr.getResponseHeader("Host");
var allHeaders= xhr.getAllResponseHeaders();
} else{
alert("Request was unsuccessful" + xhr.status);
}
}
};
xhr.open("get","example.html",true);
xhr.setRequestHeader("Host","https://www.baidu.com");
xhr.send(null);
注:我在頁面上寫了個按鈕和div區(qū)域,點擊按鈕時想向某站發(fā)送請求,然后將響應寫到div中,出現(xiàn)了以下的錯誤:
Refused to set unsafe header "User-Agent"
Access to XMLHttpRequest at 'file:///K:/%E….' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.
我本來是打算利用js來像python那樣實現(xiàn)爬取內容的,但發(fā)現(xiàn)不行。
function submitData() {
var xhr=createXHR();
xhr.onreadystatechange= function () {
if (xhr.readyState ==4) {
if ((xhr.status >=200 && xhr.status < 300) || xhr.status ==304) {
alert(xhr.responseText);
} else {
alert("Request was unsuccessful: " + xhr.status);
}
}
};
xhr.open("post", "postexample.php", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
var form= document.getElementById("user-info");
xhr.send(serialize(form));
}
post請求在open中的第一個參數(shù)是get,在send中是經過序列化的字符串,具體見serialize函數(shù)。
FormData類型可以方便的對數(shù)據(jù)進行序列化,這個主要是用在post方式:
var data= new FormData();
data.append("name","伍德春");
也可以直接將form作為實例化的參數(shù):
var data= new FormData(document.forms[0]);
創(chuàng)建好data后,就可以將其作為send()方法的參數(shù)進行發(fā)送了。
xhr.send(new FormData(document.forms[0]));
在xhr.open與xhr.send之間,通過xhr.timeout=1000來設定超時時間,通過xhr.ontimeout=function(){//超時處理代碼};來作為超時處理程序。
使用此方法可以保證把響應當作指定的類型來處理,方法需要在open與send之間
// 設置為XML
xhr.overrideMimeType("text/xml");
可以利用progrss事件動態(tài)的更新進度:
xhr.onprogress = function (event) {
var divStatus= document.getElementById("status");
if (event.lengthComputable){
divStatus.innerHTML = "已接收" + event.position + "/" + event.totalSize + "字節(jié)";
}
};
這個事件處理程序的指定需要在xhr.open()方法之前。
XHR對象只能訪問與包含它的頁面位于同一域中的資源。
xhr.setRequestHeader("Origin","https://www.baidu.com");
JSON with padding填充式JSON或參數(shù)式JSON,即在請求參數(shù)中指定回調函數(shù)。
Comet是一種服務器向頁面推送數(shù)據(jù)的技術。能夠讓信息近乎實時的推送到頁面上,非常適合處理體育比賽的分數(shù)和股票報價(也適合公司車間展示信息)。
*請認真填寫需求信息,我們會在24小時內與您取得聯(lián)系。