* 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#
山代有人才出,各领风骚数百年。
Hello,大家好,我是编程三昧的作者隐逸王,小小前端一枚。
自昨天发了《还在死磕 Ajax?那可就 out 了!》一文后,收到了一些大家的一些评论,评论都很走心,也很有深度。
说实话,虽然我在尽可能努力地回复大家的问题,但还是避免不了对其中一些概念理解的模棱两可的情况,有幸得到同仁们的指点,比如:
感谢各位的不吝赐教,让我在成长的道路上又前进了几分。
现在总结一下,评论区涉及到的主要问题如下:
为了不辜负大家的热情,我在这里试着解释一下这些问题,如有疏漏,还请海涵!
首先,我们来了解一下 Ajax、Axios 和 Fetch 它们各自的概念。
英文全称为 Asynchronous JavaScript + XML ,翻译过来就是异步JavaScript和XML。
它是用来描述一种使用现有技术集合的“新”方法的,这里的“新”方法主要涉及到: HTML 或 XHTML、CSS、 JavaScript、DOM、XML、XSLT,以及最重要的 XMLHttpRequest。
当使用结合了这些技术的 AJAX 模型以后, 网页应用能够快速地将增量更新呈现在用户界面上,而不需要重载(刷新)整个页面。这使得程序能够更快地回应用户的操作。
Ajax 是一个概念模型,是一个囊括了众多现有技术的集合,并不具体代指某项技术。
Ajax 最重要的特性就是可以局部刷新页面。
Axios 是一个基于 Promise 网络请求库,作用于 Node.js 和浏览器中。 它是 isomorphic 的(即同一套代码可以运行在浏览器和 Node.js中)。在服务端它使用原生 Node.js http 模块,而在客户端则使用 XMLHttpRequest。
这里我们只关注客户端的 Axios,它是基于 XHR 进行二次封装形成的工具库。
客户端 Axios 的主要特性有:
Fetch 提供了一个获取资源的接口(包括跨域请求)。
Fetch 是一个现代的概念, 等同于 XMLHttpRequest。它提供了许多与 XMLHttpRequest 相同的功能,但被设计成更具可扩展性和高效性。
Fetch 的核心在于对 HTTP 接口的抽象,包括 Request、Response、Headers 和 Body,以及用于初始化异步请求的 global fetch。得益于 JavaScript 实现的这些抽象好的 HTTP 模块,其他接口能够很方便的使用这些功能。
除此之外,Fetch 还利用到了请求的异步特性——它是基于 Promise 的。
fetch() 方法必须接受一个参数——资源的路径。无论请求成功与否,它都返回一个 Promise 对象,resolve 对应请求的 Response。
通过上面对三者概念的解释,我们应该大体清楚它们之间的关系了,我在这里用图表示一下:
针对上图,我解释一下:
其实这个问题更准确的问法应该是:Fetch 真的会取代传统 Ajax ( XHR ) 吗?
要回答这个问题,我们需要清楚以下几点:
基于以上几点,我的观点是Fetch 终会取代传统 Ajax,但过程可能比较漫长。
虽然目前来看,传统 Ajax (比如 Axios 之类的)在使用规模上远远超过 Fetch,但要知道,这是 XHR 十来年累积下来的效果。
封装得到的 Axios 在易用性上甩了原生 XHR 十万八千里,但毕竟是封装的,和原生的 Fetch 相比较,Axios 在出身上就已略输一筹,且原生的 API 天然上会支持更多的功能,使用上会更加灵活。
在昨天文章的评论区,有一位同学推荐了一个 Fetch 工具库,名为 Mande,有兴趣的同学可以去看看。
以上就是针对 Fetch 和 Ajax 问题的一份简单解释,希望能够给大家带来启发。
就我个人而言,倒是蛮期待 Fetch 能够取代传统 Ajax,技术的发展需要不断注入活力才行,我还能再干几十年,可不希望前端技术裹足不前,那样该多无聊 !
~
~本文完,感谢阅读!
~
学习有趣的知识,结识有趣的朋友,塑造有趣的灵魂!
大家好,我是〖编程三昧〗的作者 隐逸王,我的公众号是『编程三昧』,欢迎关注,希望大家多多指教!
你来,怀揣期望,我有墨香相迎! 你归,无论得失,唯以余韵相赠!
知识与技能并重,内力和外功兼修,理论和实践两手都要抓、两手都要硬!
var xhr = new ?XMLHttpRequest();
调用的第一个方法是open()
xhr.open(method,url,false)
注:
1、如果url不是绝对路径,那么就是相对于当前页面。
2、open语句并不会立刻发送请求,需要send()方法。
3、只能向同一个域中使用相同端口和协议的URL发送请求。
要发送请求,需要再使用send方法:
xhr.send(null)
send方法的参数是指要发送的数据,如果没有的话需要写null。一般get方式不传数据,post方法需要传送数据。
xhr收到响应后,会有下面这些属性:
接到响应后,首先检查status,确定是否成功返回:
1、200响应成功;
2、304请求的资源没有被修改,可使用缓存内容;
可使用下面的代码检测响应状态:
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);
}
发送异步请求时,需要监控readyState属性,该属性有如下几个值:
每次readyState的值变化一次,就会触发一次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后面的。
下面的函数的作用是将查询字符串经过编码后拼接到URL后面:
// 对查询参数进行编码并拼接
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区域,点击按钮时想向某站发送请求,然后将响应写到div中,出现了以下的错误:
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那样实现爬取内容的,但发现不行。
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中的第一个参数是get,在send中是经过序列化的字符串,具体见serialize函数。
FormData类型可以方便的对数据进行序列化,这个主要是用在post方式:
var data= new FormData();
data.append("name","伍德春");
也可以直接将form作为实例化的参数:
var data= new FormData(document.forms[0]);
创建好data后,就可以将其作为send()方法的参数进行发送了。
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事件动态的更新进度:
xhr.onprogress = function (event) {
var divStatus= document.getElementById("status");
if (event.lengthComputable){
divStatus.innerHTML = "已接收" + event.position + "/" + event.totalSize + "字节";
}
};
这个事件处理程序的指定需要在xhr.open()方法之前。
XHR对象只能访问与包含它的页面位于同一域中的资源。
xhr.setRequestHeader("Origin","https://www.baidu.com");
JSON with padding填充式JSON或参数式JSON,即在请求参数中指定回调函数。
Comet是一种服务器向页面推送数据的技术。能够让信息近乎实时的推送到页面上,非常适合处理体育比赛的分数和股票报价(也适合公司车间展示信息)。
*请认真填写需求信息,我们会在24小时内与您取得联系。