[TOC]
AJAX概述
背景
前端的局限性
JavaScript功能强大,但JavaScript能力有限(了解AJAX之前),那就是无法提供API,所有代码都只能满足“单机需求”,无法满足与后端交互数据
这样平时的登录注册无法实现,查询信息无法实现。
这个时候就必须需要一个强大的功能,能通过API获取服务器的数据以及发送数据给数据库
发送请求
基础请求发送方式
-
地址栏输入地址
-
特定元素的src属性或href属性
-
表单提交
AJAX出现
Google Suggest
在2005年时,Google Suggest提供了 AJAX方法(Asynchronous JavaScript and XML)
但发展初,它并不是一种正式的技术
AJAX作用
为浏览器提供一套API,可以通过JavaScript直接调用,从而能实现前端向后端请求与响应
AJAX的X——XML:早期客服端与服务端之间传递数据时所用的数据格式
AJAX使用
体验如何操作AJAX
通过JQuery封装的方法
<script src="js/jquery-1.12.4.min.js"> ", type: "GET", dataType: "json", data: {"id": 1}, success: function (data) { // 使用请求成功的数据 console.log(data); } })
通过原生JS
// 1.创建一个 XMLHttpRequest 类型的对象 --- 相当于打开了一个浏览器
var xhr = new XMLHttpRequest();
// 2.打开一个与网址之间的连接 --- 相当于在地址栏输入网址
xhr.open("GET","https://jsonplaceholder.typicode.com/users");
// 3.通过连接发送一次请求 --- 相当于点击回车或者超链接
xhr.send(null);
// 4.指定 xhr 状态变化事件处理函数 --- 相当于处理网页呈现后的操作
xhr.onreadystatechange = function () {
// 通过判断 xhr 的 readyState ,确定此次请求是否完成
if (this.readyState === 4) {
console.log(this.responseText)
}
}
Ajax请求步骤
- 创建XMLHttpRequest对象
- 打开一个(网页之间的)连接
- 发送
- 指定返回状态变化事件处理函数
原生Ajax
详讲
请求步骤
- 创建XMLHttpRequest对象
- 打开一个(网页之间的)连接
- 发送
- 指定返回状态变化事件处理函数
XMLHttpRequest内置对象
创建XMLHttpRequest对象
所有Ajax操作都会使用这一个内置对象
let xhr = new XMLHttpRequest();
// IE6 兼容问题
var xhr = new ActiveObject("Microsofft.XMLHTTP");
// 兼容性写法
var xhr = null;
if(window.XMLHttpRequest
xhr = new XMLHttpRequest();
else
xhr = new ActiveXObject("Microsoft.XMLHTTP");
请求方式及目标地址:open方法
语法: xhr.open( method, url );
method 为传输方法,一般有:[GET]、[POST]、[PUT]、[DELETE]等,但实际编程中只用post和get
url 为发送请求URL地址,数据类型为String
注意:该方法必须写在send方法前面
设置请求头:setRequestHeader方法
语法:xhr.setRequestHeader( header, value );
header:一般设置"Content-Type",传输数据类型,一般为服务器需要我们传送的数据类型
value:具体的数据类型,常用:"application/x-www-form-urlencoded"和"application/json"
注意:该方法必须写在open后面和send前面
设置请求中的数据体:send方法
语法:xhr.send(body)
body为请求时发送的数据体
注意:该方法必须写在open方法后面
返回数据中的readyState属性
说明:readyState 属性返回一个 XMLHttpRequest 代理当前所处的状态,由于 readystatechange 事件是 在 xhr 对象状态变化时触发
| ready State值 | 状态描述 | 说明 |
|---|---|---|
| 0 | UNSEND | 代理XHR被创建,但未调用open方法 |
| 1 | OPENED | open方法已经被调用,并且已经创建连接 |
| 2 | HEADERS_RECEIVED | send方法已经被调用,并且已经可以获取状态行和响应头 |
| 3 | LOADING | 响应体下载中, responseText 属性可能已经包含部分数据 |
| 4 | DONE | 响应体下载完成,可以直接使用responseText |
0-4表示返回请求的5个状态
事件处理
建议:一般事件处理都是在后端返回所有数据后,也就是 readyState=4 时
方法:
xhr.onreadystatechange = function() {
if (this,readyState === 4) {
// 后续操作
}
}
不同的传输方式对应不同的方法
post传输方式
1、必须设置请求头
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
2、能通过send设置传参
xhr.send("name=harry&age=19");
get传输方式
1、不用设置请求头
2、get方法无法使用send传参,只能通过网址传输
3、请求还是要通过send传输
同步与异步
同步:等待上一个事件完成后才进行下一步操作
异步:上一个事件还在处理时,不等待直接进行下一步操作
Ajax中的同步与异步
xhr.open()方法可以设置第三个参数,其作用为本次请求是同步还是异步方式执行
数据类型为布尔型,默认值为true,表示是异步执行,若是要进行同步执行则设置为false
采用同步方式执行,则代码会卡死在 xhr.send() 这一步
使用建议:
为了让这个事件一定触发,在发送请求 send() 之前,一定是先注册 readystatechange
正常开发时,不建议使用同步模式
响应数据格式
XML
一种数据描述手段,已经被淘汰
<?xml verson="1.0" encoding="utf-8" ?>
<booklist>
<book>
<name>三国演义</name>
<author>罗贯中</author>
<cate>古典名著</cate>
</book>
<book>
<name>西游记</name>
<author>吴承恩</author>
<cate>古典名著</cate>
</book>
<book>
<name>红楼梦</name>
<author>曹雪芹</author>
<cate>古典名著</cate>
</book>
</booklist>
前端淘汰原因:
-
元数据占用数据量比较大(数据利用率低),不利于大量数据网络传输
-
js内部解析时,方法比较复杂
JSON
JavaScript Object Notation,JavaScript 对象表示法
一种数据描述手段,类似于JS中的对象
现在前后端传输都是用 JSON 格式交互数据
注意
无论是已经被淘汰的XML还是现在常用的JSON都是一种数据协议,与AJAX没有必然联系
不管服务端是采用 XML 或 JSON ,本质上都是将数据返回给客户端
JSON Server
json-server 是一个 Node 模块,我们可以使用它快速的搭建一个 web 服务器
使用步骤:
-
在命令窗口通过node 下载json-server插件,下载代码为:
npm install -g json-server -
在json所在位置使用控制终端,输入
json-server --watch 文件名.json -
服务器驱动的json文件书写格式:
{
"路径地址":{"属性名":"属性值"},
"下一个路径":[
{"属性名":"属性值"},
{"属性名":"属性值"},
{"属性名":"属性值"},
{"属性名":"属性值"}
]
}
- 服务器驱动成功
原生AJAX具体用法
GET请求
通常在一次 GET 请求过程中,参数传递都是通过 URL 地址中的 ? 参数传递
get请求无需设置请求头
无需设置响应体,可以传输 null 或者不传
POST请求
POST请求过程都是采用请求体承载交互的数据
必须设置请求头的“Content-Type”,以便于服务端接受对应的数据体
需要提交到服务器的数据可以通过send方法传参
渲染响应数据
通过dom节点操作将客户需要的数据渲染上去
封装AJAX库
一般用第三方的AJAX库,因为第三方封装的库比自己封装的要更加严谨
JQuery的AJAX
JQuery有一套完整的AJAX封装
注意:ajax技术包括 DOM、XML、JavaScript
$.ajax()方法
常用参数
| 参数名 | 说明 | 例子 |
|---|---|---|
| url | 请求地址 | "www.baidu.com" |
| type | 请求方法,默认为 "get" | get、post、delete |
| dataType | 服务器响应数据类型类型 | |
| contentTyep | 请求体内容类型 | application/x-www-form-urlencoded |
| data | 传递到服务器的数据类型 | |
| timeout | 请求超时时间 | |
| beforeSend | 请求发起之前触发 | |
| success | 请求成功后触发 | |
| error | 请求失败触发 | |
| complete | 请求完成后触发(无论请求成功与否) |
$.ajax({
url: "http://localhost:3000/posts",
type: "post",
contentType:"application/json",
dataType: "json",
data: JSON.stringify( {"id": 2}),
beforeSend: function (xhr) {
console.log("before send");
},
success: function (data) {
console.log(data);
},
error: function (xhr) {
console.log(xhr);
},
complete: function (xhr) {
console.log(xhr);
}
});
GET请求
通过ajax自己封装的get方法
语法: $.get(url,data,callback)
$.get("http://local:3000/test",
{
"id":1,
name:"Tom"
},
function(data){
// data为回调数据
console.log(data);
}
)
POST请求
通过ajax自己封装的post方法
语法: $.post(url,data,callback)
$.post("http://local:3000/test",
{
"id":1,
name:"Tom"
},
function(data){
// data为回调数据
console.log(data);
}
)
其他方式请求
put:
$.ajax({
url: "http://localhost:3000/comments/4",
type: "put",
dataType: "json",
data: {"content": "good", "postId": 2},
success: function (data) {
console.log(data)
}
})
delete:
$.ajax({
url: "http://localhost:3000/comments/5",
type: "delete",
success: function (data) {
console.log(data)
}
})
设置ajax默认属性:$.ajaxSetup方法
$.ajaxSetup({
url:"localhost:3000",
type:"post",
contentType:"application/json",
dataType:"json"
});
//设置ajax默认属性,方便以后调用
Ajax升级——Axios
注意:jQuery1.12.X没有Axios库,只有ajax
引用方法:
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<!-- 或者把网页上面的axios.min.js下载下来,直接本地调用 -->
Axios API
通过axios方法相关配置来传递创建请求
语法:axios( url , config ) 或者 axios( config )
url一般为请求地址
config为请求配置
// 配置示例
{
method:"post",
url :"localhost:8080/login",
headers:{
contentType:"application/json"
}
dataType :"json",
data: JSON.stringify({
"name":"Tom",
"age":20
})
}
| 常用配置项 | 说明 |
|---|---|
| url | 用于请求的服务器地址,必须写 |
| method | 创建请求时用的方法 |
| baseURL | 传递相对URL前缀,会自动添加在url前面 |
| headers | 自定义请求头 |
| params | 将参数放置在地址栏,随着地址栏进行请求 |
| data | 作为请求主体时被发送的数据 |
| timeout | 指定请求超时的毫秒数(0表示无超时设置) |
| responseType | 表示服务器响应的数据类型,默认为"json" |
后续请求成功的方法: then方法
请求成功后,axios有自己封装好的方法:then方法
axios().then(function(response){
// 正常请求成功后,响应信息对象 response
// response 可以简写为 res
// 后续数据渲染或者其他网页操作都是靠response中的数据
})
后续请求失败的方法:catch方法
若请求失败,axios有自己封装好的方法:then方法
axios().then().catch(function(error){
// 请求出错时,error为捕获出错对象
// error 可以简写成 err
})
全局配置设置
可以指定引用的axios的默认设置,便于后续操作
axios.defaults.baseURL = "https://localhost:8080";
axios.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
拦截器
请求或者响应在 then 及 catch 处理前拦截
// 请求前后的拦截器(请求拦截器)
axios.interceptors.request.use( function(config){
// 发送请求之前做什么
return config;
} , function(error){
// 请求出错时做什么
return Promise.reject(error);
} )
// 响应前后的拦截器(响应拦截器)
axios.interceptors.response.use( function(response){
// 接收到响应数据后做啥
return response;
} , function(error){
// 响应数据出错后做啥
return Promise,reject(error);
} )
快速请求方法
get的快速请求方法:axios.get( url [ , config ] )
post的快速请求方法:axios.post( url [ , config ] )
delete的快速请求方法:axios.delete( url [ , config ] )
put的快速请求方法: axios.put( url [ , config ] )
// 示例:get快速请求
axios.get("/post",{
params:{ id : 1 },
baseURL:"localhost:3000"
})
.then(function(res){
console.log(res.data);
})
.catch(function(err){
console.log(err);
});
// 示例:post快速请求
axios.post("/post",{
headers:{
contentType:"applaction/json"
},
baseURL:"localhost:3000",
responseType:"json",
data:JSON.stringify({id:1})
})
.then(function(res){
console.log(res.data);
})
.catch(function(err){
console.log(err);
});
原生JS中XMLHttpRequest2.0
内置的onload方法
触发时间:readyState = 4,也就是说在请求结束后
xhr.onload = function(){
console.log(this.readyState);
};
内置的onprogress方法
触发时间: readyState = 3 ,也就是说在获取响应时,不是获取完整响应时
xhr.onprogress = function(e){
console.log(this.readyState);
// e.loaded 为接收到数据个数
console.log(e.loaded);
// e.total 为接受数据的总个数
console.log(e.total);
}
内置的responseType属性
该属性是设置请求数据类型
注意:该方法要写在open方法初始化之后,send方法之前
xhr.responseType = "json";
跨域和模板引擎应用
同源
什么是同源
同源指在同一服务器
如何判定:
服务器地址一样,便是同源;后面请求地址与 是否同源无关系
服务器地址由三部分构成:
| 说明 | 例子 |
|---|---|
| 传输协议 | http、https |
| 域名/IP地址 | www.lagou.com 、 14.215.177.38 |
| 端口号 | :8080 、 :4200 |
注意: localhost 与 127.0.0.1 同源
同源策略
在同源情况下,Ajax能在同源中进行正常访问,但是无法跨域访问
这是一种浏览器的安全策略
不同源地址请求称之为跨域请求
跨域解决方案
JSONP
原理:在客户端接用script标签请求服务器的一个地址
- JSONP (JSON with Padding),是一种借用script标签发送跨域请求的技巧
- 服务器响应后,会返回一段某个全局函数调用的JavaScript脚本
- 在调用函数中,原本需要返回给客户端的数据通过参数传递给这个函数
- 之后客户端的函数就可以通过参数得到原本服务器返回的数据
// 动态生成 script 标签
var script= document.createElement("script");
script.src = "localhost:8888/data.php?callback=fun"
// callback意思是回调函数
// 添加到head标签内部
var head = document.getElementsByTagName("head")[0];
head.appendChild(script);
// 客户端定义回调函数
function fun( data ) {
console.log(data);
}
示意:服务器的响应
注意:JSONP只能发送 GET 请求
JSONP使用的是 script 标签 ,与 AJAX、XMLHttpRequest 没有任何关系
JQuery中封装的JSONP
jQuery中使用JSONP 方式 仅仅是 设置 dataType 为 jsonp 即可
$.ajax({
url: "https://www.baidu.com/sugrec?pre=1&p=3&ie=utf-8&json=1&prod=pc&from=pc_web",
type: "GET",
dataType: "jsonp",
jsonp: "cb", //设置回调函数的参数名称(必须与后台接口的回调函数参数名保持一致)
jsonpCallback: "abc", // 重命名回调函数
data: {"wd": "ajax"},
success: function (data) {
console.log(data)
}
})
CORS
全称: Cross Origin Resource Share,跨域资源共享
该方法无需客户端做出任何变化,只是在请求的服务器响应时添加一个 Access-Control-Allow-Origin 的响应头,表示该资源是否允许指定域请求。
Access-Control-Allow-Origin的值为
* 表示允许任意资源访问,不安全
http:// fool.com 允许指定的源访问
<?php
header("Access-Control-Allow-Origin:http://foo.example");
header("Access-Control-Allow-Origin:*");
?>
模板引擎
作用:减少字符串拼接,便于开发
模板中解析json,之后跟html内容拼接
模板例子:artTemplate
一种简约、快捷的模板引擎
网址:github.com/aui/artTemp… 中文使用文档:aui.github.io/art-templat…
语法规则:
- 原始语法
| 语法 | 说明 |
|---|---|
| <% %> | 模板逻辑表达式,包括 if、for 等逻辑语句 |
| <%= %> | 输出表达式 |
- 标准语法
| 语法 | 说明 |
|---|---|
| {{ if user }} {{/if}} | 模板逻辑表达式,包括 if、for 等逻辑语句 |
| {{ user.name }} | 输出表达式 |
使用规则:
在调用之前引入模板引擎,并在引擎下通过 script 标签写入模板
script 标签
原始版
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test02</title>
<script src="js/template-native.js"></script>
<script id="test" type="text/html">
<!-- 定义模板 -->
<% if (name%2==0){ %>
<h2><%= name %></h2>
<%}%>
</script>
</head>
<body>
<div id="box">
</div>
<script src="js/jquery-1.12.4.min.js"></script>
<script>
for(let i = 0 ;i<20;i++)
$("#box").append(template("test",{name:i}));
</script>
</body>
</html>
标准版
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test02</title>
<script src="https://unpkg.com/art-template/lib/template-web.js"></script>
<script id="test" type="text/html">
<!-- 定义模板 -->
{{if name%2==0}}
<h2>{{name}}</h2>
{{/if}}
</script>
</head>
<body>
<div id="box">
</div>
<script src="js/jquery-1.12.4.min.js"></script>
<script>
for(let i = 0 ;i<20;i++)
$("#box").append(template("test",{name:i}));
</script>
</body>
</html>