jax在前端开发中有着举足轻重的地位,关于Ajax的使用和注意事项一直是一个重要的话题,借此机会,本文希望对Ajax做一个全面的总结,彻底揭开Ajax的神秘面纱。
Ajax(Asynchronous JavaScript and XML),可以理解为JavaScript执行异步网络请求。通俗的理解的话就是,如果没有Ajax技术,改变网页的一小部分(哪怕是一行文字、一张图片)都需要重新加载一次整个页面,而有了Ajax之后,就可以实现在网页不跳转不刷新的情况下,在网页后台提交数据,部分更新页面内容。
XMLHttpRequest 对象用于在后台与服务器交换数据,能够在不重新加载页面的情况下更新网页,在页面已加载后从服务器请求数据,在页面已加载后从服务器接收数据,在后台向服务器发送数据。所以XMLHttpRequest对象是Ajax技术的核心所在。
创建 XMLHttpRequest对象——>打开请求地址,初始化数据——>发送请求数据——>监听回调函数状态——>收到服务器返回的应答结果。
下面用具体的代码进行解释:
var xmlhttp; function loadXMLDoc(url) { xmlhttp=null; if (window.XMLHttpRequest) {// code for all new browsers xmlhttp=new XMLHttpRequest();//在这里创建 XMLHttpRequest对象 } else if (window.ActiveXObject) {// code for IE5 and IE6 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } if (xmlhttp!=null) { xmlhttp.open("GET",url,true); //请求的方式和请求地址 xmlhttp.send(null);//发送请求 xmlhttp.onreadystatechange=state_Change;//监听回调函数 } else { alert("Your browser does not support XMLHTTP."); } } function state_Change() //这里是回调函数 { if (xmlhttp.readyState==4&&xmlhttp.status==200) //当满足这两个条件时表示请求成功,完成响应 4="loaded", 200=OK { var data=xmlhttp.responseText; //拿到服务器返回的数据 // ...our code here...在这里进行数据返回后的操作 }else { alert("Problem retrieving XML data"); } }
(1).open() 的第三个参数中使用了 "true",该参数规定请求是否异步处理,默认是异步。True 表示脚本会在 send() 方法之后继续执行,而不等待来自服务器的响应。
(2).关于readyState
(3).关于status 由服务器返回的 HTTP 状态代码,200 表示成功,而 404 表示 "Not Found" 错误。当 readyState 小于 3 的时候读取这一属性会导致一个异常。(后面会有http状态码的详细解读)
JQuery对原生Ajax做了很好的封装,使用起来非常简单方便,具体的很多方法如 $.ajax,$.post, $.get, $.getJSON等能根据不同需要进行调用,写法更加简洁,但是为了兼顾各个方法在这里我以一个通用的方法 $.ajax为例做一个简单的解析,按照下面的模式写好各个参数,就能成功进行Ajax的请求了,可能在实际中使用 $.post, $.get 这两个方法使用比较多,但是理解$.ajax 这个通用的方法能对封装原理有很好的认识。
$.ajax({ type: //数据的提交方式:get和post url: //请求地址 async: //是否支持异步刷新,默认是true data: //需要提交的数据 dataType: //服务器返回数据的类型,例如xml,String,Json等 success:function(data){ } //请求成功后的回调函数,参数data就是服务器返回的数据 error:function(data){ } //请求失败后的回调函数,根据需要可以不写,一般只写上面的success回调函数 })
作为Ajax最常用的两种数据提交方式,GET和POST有着自己的特点和适用场景,正确区分GET和POST的不同并根据实际需要进行选用在开发中十分重要,简单但是关键!
先上一张GET 和 POST的比较图,从这张图中可以看出两者之间的差别:
从表格中拎出关键点: 1.传递数据的方式不同:get是直接把请求数据放在url的后面,是可见的,post的请求数据不会显示在url中,是不可见的。 2.数据长度和数据类型的差异:get有数据长度的的限制,且数据类型只允许ASCII字符,post在这两方面都没有限制。 3.安全性的差异:get不安全,post更安全。
由此得出的两者的使用场景:get使用较方便,适用于页面之间非敏感数据的简单传值,post使用较为安全,适用于向服务器发送密码、token等敏感数据。
JQuery封装的Ajax回调函数中,success、error、complete是最常用的三个,其中,success和error很好区别,一个是请求成功调用的,另一个是请求失败调用的,从字面上就可以理解。但是success和complete容易混淆,在这里特别做一个说明:
success:请求成功后回调函数。
complete:请求完成后回调函数 (请求成功或失败时均调用)。
注意到括号里面了吗,没错,区别就在于complete只要请求完成,不论是成功还是失败均会调用。也就是说如果调用了success,一定会调用complete;反过来调用了complete,不一定会调用success。(状态码404、403、301、302...都会进入complete,只要不出错就会调用)
Ajax中的是 "x" 指的就是XML。
xml:可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。
xml作为一种数据交互格式,广泛用在计算机领域,然而,随着json的发展,json以其明显的优势已经渐渐取代了xml成为现在数据交互格式的标准,所以在这里,想强调的是,json现在是主流的数据交互格式,前后端的交互标准,无论是前端提交给后台的数据,还是后台返回给前端的数据,都最好统一为json格式,各自接收到数据后再解析数据即可供后续使用。所以 "Ajax" 实际上已经发展为 "Ajaj"
json 和 jsonp 看起来只相差了一个 “p” ,然而实际上根本不是一个东西,千万别以为是差不多的两个概念。
json:(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式。
jsonp:一种借助 <script> 元素解决主流浏览器的跨域数据访问问题的方式。
ajax很好,但不是万能的,ajax的请求与访问同样会受到浏览器同源策略的限制,不能访问不同主域中的地址。所以,为了解决这一问题,实现跨域访问,有很多种方式,上述提到的jsonp就是一种流行的方式,还有其他一些方式,我在这里就不展开说了,只是想说明ajax的使用也是有条件的,任何技术的实现都不会是没有限制的。跨域访问时一个很重要的知识点,之前专门写过一篇关于跨域访问的总结,还挺详细的,可以移步查看: javascript中实现跨域的方式总结
前面提到的"200"、"404"只是http状态码中常见的两个,当浏览者访问一个网页时,浏览者的浏览器会向网页所在服务器发出请求。当浏览器接收并显示网页前,此网页所在的服务器会返回一个包含HTTP状态码的信息头(server header)用以响应浏览器的请求。
需要掌握的常见http状态码大致有以下一些:
101:切换协议,服务器根据客户端的请求切换协议 **200:请求成功。一般用于GET与POST请求** **301:永久重定向** **302:临时重定向** 303:与301类似。使用GET和POST请求查看 **304:请求资源未修改,使用缓存** 307:与302类似。使用GET请求重定向 **404:客户端请求失败** 408:请求超时 **500:内部服务器错误,无法完成请求** 505:服务器不支持请求的HTTP协议的版本,无法完成处理
http请求中的一个重要关注点就是请求头和响应头的内容,从这两个头文件中可以看出很多东西,当我们用发送一个ajax请求的时候,如果没有达到预期的效果,那么就需要打开浏览器的调试工具,从NetWork中找到相应的ajax请求,再通过查看请求头和响应头的信息,大体会知道这次请求的结果是怎么样的,结合响应的主体内容,可以很快找到问题。所以学会看http的头文件信息是前端开发中必须掌握的一个技能,下面就来看看具体的头文件信息。
首先随便上一张sf中的完成一个搜索结果的http请求,可以从图中的右侧清楚看到请求头和响应头的内容,包括了很多个字段信息,这些字段信息就是我们需要掌握的知识点,下面挑出其中的重点字段进行分析。
Accept:客户端支持的数据类型 Accept-Charset:客户端采用的编码 Accept-Encoding:客户端支持的数据压缩格式 Accept-Language:客户端的语言环境 Cookie:客服端的cookie Host:请求的服务器地址 Connection:客户端与服务连接类型 If-Modified-Since:上一次请求资源的缓存时间,与Last-Modified对应 If-None-Match:客户段缓存数据的唯一标识,与Etag对应 Referer:发起请求的源地址。
content-encoding:响应数据的压缩格式。 content-length:响应数据的长度。 content-language:语言环境。 content-type:响应数据的类型。 Date:消息发送的时间 Age:经过的时间 Etag:被请求变量的实体值,用于判断请求的资源是否发生变化 Expires:缓存的过期时间 Last-Modified:在服务器端最后被修改的时间 server:服务器的型号
Pragma:是否缓存(http1.0提出) Cache-Control:是否缓存(http1.1提出)
(1) 强制缓存 expire 和 cache-control
(2) 对比缓存 Last-Modified 和 If-Modified-Since Etag 和 If-None-Match
安全问题,对一些网站攻击,如csrf、xxs、sql注入等不能很好地防御。
* JSON 使用 JavaScript 语法来描述数据对象,但是 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;} // 不能使用函数和日期对象
}
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 格式有两个显著的优点:书写简单,一目了然;符合 JavaScript 原生语法,可以由解释引擎直接处理,不用另外添加解析代码。所以,JSON迅速被接受,已经成为各大网站交换数据的标准格式,并被写入ECMAScript 5,成为标准的一部分。
XML和JSON都使用结构化方法来标记数据,下面来做一个简单的比较。
用XML表示中国部分省市数据如下:
<?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 容易阅读,并且在数据交换方面,由于 JSON 所使用的字符要比 XML 少得多,可以大大得节约传输数据所占用的带宽。
AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)。
AJAX除了异步的特点外,还有一个就是:浏览器页面局部刷新;(这一特点给用户的感受是在不知不觉中完成请求和响应过程)
示例:
页面输入两个整数,通过AJAX传输到后端计算出结果并返回。
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:{}, // 请求的参数
success:function(arg){
// 收到响应之后要做的事
}
})
搜索引擎根据用户输入的关键字,自动提示检索关键字。
还有一个很重要的应用场景就是注册时候的用户名的查重。
其实这里就使用了AJAX技术!当文件框发生了输入变化时,使用AJAX技术向服务器发送一个请求,然后服务器会把查询到的结果响应给浏览器,最后再把后端返回的结果展示出来。
当输入用户名后,把光标移动到其他表单项上时,浏览器会使用AJAX技术向服务器发出请求,服务器会查询名为lemontree7777777的用户是否存在,最终服务器返回true表示名为lemontree7777777的用户已经存在了,浏览器在得到结果后显示“用户名已被注册!”。
优点
最基本的jQuery发送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参数
data参数中的键值对,如果值值不为字符串,需要将其转换成字符串类型。
$("#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中发送。
$.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中的字符串 放置在请求头中发送。
注意:需要引入一个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请求统一设置。
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)
我们的数据中经常有日期时间,也就是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")
}
}
})
});
})
#科技##软件开发##python#
AJAX 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式网页应用的网页开发 技术。
ajax 是一种浏览器通过 js 异步发起请求,局部更新页面的技术。
Ajax 请求的局部更新,浏览器地址栏不会发生变化
局部更新不会舍弃原来页面的内容
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="pragma" content="no-cache" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
// 在这里使用 javaScript 语言发起 Ajax 请求,访问服务器 AjaxServlet 中 javaScriptAjax
function ajaxRequest() {
// 我们首先要创建 XMLHttpRequest
var xmlhttprequest=new XMLHttpRequest();
// 调用 open 方法设置请求参数
xmlhttprequest.open("GET","http://localhost:8080/Test/ajaxServlet?action=javaScriptAj
ax",true)
// 在 send 方法前绑定 onreadystatechange 事件,处理请求完成后的操作。
xmlhttprequest.onreadystatechange=function(){
if (xmlhttprequest.readyState==4 && xmlhttprequest.status==200) {
var jsonObj=JSON.parse(xmlhttprequest.responseText);
// 把响应的数据显示在页面上
document.getElementById("div01").innerHTML=" 编号:" + jsonObj.id + " , 姓名:" +
jsonObj.name;
}
}
// 调用 send 方法发送请求
xmlhttprequest.send();
}
</script>
</head>
<body>
<button onclick="ajaxRequest()">ajax request</button>
<div id="div01">
</div>
</body>
</html>
$.ajax 方法
url 表示请求的地址
type 表示请求的类型 GET 或 POST 请求
data 表示发送给服务器的数据
格式有两种:
一:name=value&name=value
二:{key:value}
success 请求成功,响应的回调函数
dataType 响应的数据类型
常用的数据类型有:
text 表示纯文本
xml 表示 xml 数据
json 表示 json 对象
$("#ajaxBtn").click(function(){
$.ajax({
url:"http://localhost:8080/Test/ajaxServlet",
// data:"action=jQueryAjax",
data:{action:"jQueryAjax"},
type:"GET",
success:function (data) {
// alert(" 服务器返回的数据是: " + data);
// var jsonObj=JSON.parse(data);
$("#msg").html(" 编号:" + data.id + " , 姓名:" + data.name);
},
dataType : "json"
});
});
方法和.post 方法
url 请求的 url 地址
data 发送的数据
callback 成功的回调函数
type 返回的数据类型
// ajax--get 请求
$("#getBtn").click(function(){
$.get("http://localhost:8080/Test/ajaxServlet","action=jQueryGet",function (data) {
$("#msg").html(" get 编号:" + data.id + " , 姓名:" + data.name);
},"json");
});
// ajax--post 请求
$("#postBtn").click(function(){
$.post("http://localhost:8080/Test/ajaxServlet","action=jQueryPost",function (data)
{
$("#msg").html(" post 编号:" + data.id + " , 姓名:" + data.name);
},"json");
});
$.getJSON 方法
url 请求的 url 地址
data 发送给服务器的数据
callback 成功的回调函数
// ajax--getJson 请求
$("#getJSONBtn").click(function(){
$.getJSON("http://localhost:8080/Test/ajaxServlet","action=jQueryGetJSON",function
(data) {
$("#msg").html(" getJSON 编号:" + data.id + " , 姓名:" + data.name);
});
});
表单序列化 serialize() serialize()可以把表单中所有表单项的内容都获取到,并以 name=value&name=value 的形式进行拼接。
// ajax 请求
$("#submit").click(function(){
// 把参数序列化
$.getJSON("http://localhost:8080/Test/ajaxServlet","action=jQuerySerialize&" +
$("#form01").serialize(),function (data) {
$("#msg").html(" Serialize 编号:" + data.id + " , 姓名:" + data.name);
});
});
欢迎关注公众号:愚生浅末。
*请认真填写需求信息,我们会在24小时内与您取得联系。