这是我参与8月更文挑战的第15天,活动详情查看:8月更文挑战
关于Ajax
01. Ajax
(1)是什么
Ajax是一种用于创建快速动态网页的技术Ajax用来与后台交互Ajax可以实现页面无刷新更新数据Ajax的API中核心提供的是一个XMLHttpRequest类型,所有的AJAX操作都需要使用这个类型
(2)怎么做?
创建一个新的HTTP请求
-
指定请求的methods、URL,以及是否异步处理请求:
xhr.open(methods, url, true)methods:请求方法url:请求地址boolean:用于设置此次请求是否采用异步方式执行-
true——异步;false——同步
-
同步执行,代码会卡在
xhr.send()这一步,等到所有的数据都传输完成,才会往下执行且,全部的数据传输完成后,
readystate将不再变化因此,
onreadystatechange事件不会被触发onreadystatechange事件,只有在readystate变化的时候才会被触发- 可以在
send()方法之前注册事件
请求参数
-
GET请求:拼接在URL后面
xhr.open("get","请求地址?" + params) -
POST请求:请求体中
// application/x-www-form-urlencoded var params = "name=" + name + "&age=" + age // application/json var params = { name: 'name', age: 'age' } xhr.send(params)
服务器响应
-
onloadxhr.onload = () => { let responseText = JSON.parse(xhr.responseText) console.log(responseText) } -
onReadyState- 一般都是在
readyState == 4时,执行响应的后续逻辑
// 当ajax状态码发生变化的时候触发 xhr.onreadystatechange = () => { console.log(xhr.readyState) } - 一般都是在
(3)封装
- 基本步骤
// 1.创建 XMLHttpRequest 对象
var xhr = new XMLHttpRequest()
// 2.创建一个新的HTTP请求,并指定请求的methods、URL,以及是否异步处理请求
xhr.open('GET', url, true)
// 3.设置响应头请求内容编码类型
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
// 4.发送HTTP请求
xhr.send(null)
// 5.获取服务器响应数据
xhr.onreadystatechange = function () {
if(this.readyState === 2){
// 接收到响应头
console.log("HEADERS_RECEIVED", xhr.readyState)
}else if(this.readyState === 3){
// 响应体加载中
console.log("LOADING", xhr.readyState)
}else if(this.readyState === 4){
// 加载完成
console.log("DONE", xhr.readyState)
}
}
- 方法
function ajax(options){
// 设置默认值
var defaults = {
type: "get",
url: "",
data: {},
header: {
"content-Type": "application/x-www-form-urlencoded"
},
success: function(){},
error: function(){}
};
// 浅拷贝,如果设置了对应属性的值,则使用该值,没有设置属性值,则使用默认值
Object.assign(defaults, options)
// 创建ajax对象
var xhr = new XMLHttpRequest()
// 拼接请求参数的对象
var params = "";
for(var attr in defaults.data){
// 将参数转换为字符串格式
params += attr + "=" + defaults.data[attr] + "&"
}
// 截取字符串,取消最后一个 & 符号
params = params.substr(0, params.length-1)
// 判断请求方式
if(defaults.type == "get" ){
// 如果是GET请求,就将参数拼接在请求地址中
defaults.url = defaults.url + "?" + params
}
// 配置ajax对象
xhr.open(defaults.type, defaults.url)
// 发送请求
if(defaults.type == "post"){
// POST请求---
// 用户希望向服务器端传递的请求参数的类型
var contentType = defaults.header["Content-Type"]
// post请求必须设置请求报文
xhr.setRequestHeader("Content-Type",contentType)
// post请求要send参数
// 判断类型
if(contentType == "application/json"){
// 如果是JSON格式,需要将传进来的JSON对象,转换为JSON字符串
xhr.send(JSON.stringify(defaults.data))
}else{
// 传递拼接的字符串参数
xhr.send(params)
}
}else{
// GET请求---
xhr.send()
}
// 监听onload事件
xhr.onload = function(){
// xhr.getResponseHeader(),获取响应头中的数据
var contentType = xhr.getResponseHeader("Content-Type")
// 获取服务器端返回的数据
var responseText = xhr.responseText
// 如果响应类型中包含application/json,即为JSON数据格式
if(contentType.include("application/json")){
// 将从服务器端响应得到的数据,从JSON字符串格式转换为JSON对象格式
responseText = JSON.parse(responseText)
}
// 判断请求是否成功
if( xhr.status == 200){
defaults.success(responseText, xhr)
}else{
defaults.error(responseText, xhr)
}
}
}
ajax({
// 请求方式
type: "get",
// 请求地址
url: "URL",
// 请求参数
data: {
name: "Ruovan",
age: 24
},
// 请求报文类型
header: {
"Content-Type": "application/x-www-form-urlencoded"
},
// 请求成功
success: function(data) {
console.log(data)
},
// 请求失败
error: function(data, xhr){
console.log(data)
console.log(xhr)
}
})
02. 关于JSON
- 字符串转对象:
JSON.parse() - 对象转字符串:
JSON.stringify()
03. 关于请求方式
-
GET:- 一般用于信息获取,使用URL传递参数
- GET请求参数在URL中
- GET速度比POST块
- 对所发送信息的数量也有限制,一般在2000个字符
-
POST:- 一般用于修改服务器上的资源
- 需要设置请求头,规定请求数据的类型
- POST请求参数才请求体中,POST比GET更安全
- 对所发送的信息没有限制
GET请求需要使用Request.QueryString来取得变量的值- 而
POST请求方式通过Request.Form来获取变量的值- 也就是说Get是通过地址栏来传值,而Post是通过提交表单来传值
-
然而,在以下情况中,请使用 POST 请求:
- 无法使用缓存文件(更新服务器上的文件或数据库)
- 向服务器发送大量数据(POST 没有数据量限制)
- 发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠
04. 关于跨域
(1)产生原因?
- 浏览器的同源政策导致的,无法向非同源地址发送Ajax请求,如果请求,浏览器就会报错
- 协议、域名、端口、IP的不同,都会导致跨域
(2)如何解决?
jsonp:只能解决GET跨域
-
动态创建一个
<script>标签,利用<script>标签的src属性不受同源策略限制的特性所有的
src和href属性都不受同源政策的限制,可以请求第三方服务器数据内容比如:外部的图片资源,外部的JS文件等等
-
服务器端响应数据必须是一个函数的调用,真正要发送给客户端的数据需要作为函数调用的参数
// 1. 动态创建一个script标签
let script = document.createElement("script")
// 2. 设置script标签的 src 属性为 接口地址/服务器地址 并带一个 callback 回调函数名称
script.src = "http://127.0.0.1:8888/index.php?callback=jsonpCallback"
// 3. 将script标签 插入到页面
document.head.appendChild(script)
// 4. 通过回调函数 去接收后台返回数据
function jsonpCallback(data){
// jsonp返回的数据是json对象,可以直接使用
// 但如果是 ajax 取得数据是json字符串,需要转换成json对象才可以使用
}
CORS跨域资源共享
-
原理:服务器设置
Access-Control-Allow-OriginHTTP响应头之后,浏览器将会允许跨域请求 -
限制:浏览器需要支持HTML5,可以支持POST,PUT等方法,兼容ie9以上
// 在服务器设置
// 允许所有域名访问
Access-Control-Allow-Origin: "*"
// 只允许指定域名访问
Access-Control-Allow-Origin: "http://a.com"
document.domain
- 原理:相同主域名不同子域名下的页面,可以设置
document.domain让它们同域 - 限制:同域
document提供的是页面间的互操作,需要载入iframe页面
// URL http://a.com/foo
// 1. 创建 iframe 标签
var ifr = document.createElement('iframe')
// 2. 设置src属性为服务器地址
ifr.src = 'http://b.a.com/bar'
ifr.onload = function(){
var ifrdoc = ifr.contentDocument || ifr.contentWindow.document
ifrdoc.getElementsById("foo").innerHTML)
};
// 4. 隐藏 iframe
ifr.style.display = 'none'
// 5. 插入页面
document.body.appendChild(ifr)
Apache
- 做转发(逆向代理),让跨域变成同域
服务器解决
- 同源政策是浏览器给予Ajax技术的限制**,服务器端不存在同源政策限制**
- 首先让1号客户端向1号服务器端发送请求
- 然后由1号服务器端访问2号服务器端的数据
- 最后让1号服务器端获取的数据响应给1号客户端
05. 关于状态码
-
2开头状态码- 表示成功处理了请求的状态代码
-
3开头的状态码- (重定向) 表示要完成请求,需要进一步操作。 通常,这些状态代码用来重定向。
-
4开头的状态码- 表示请求可能出错,妨碍了服务器的处理
message = '400:请求错误' message = '401:未授权,请重新登录' message = '403:拒绝访问' message = '404:请求资源不存在' message = '405:请求方法不允许' message = '408:请求超时' -
5开头的状态码- 码表示服务器在尝试处理请求时发生内部错误。
- 这些错误可能是服务器本身的错误,而不是请求出错
- 也可能是请求参数错误,服务器无法处理这个参数
message = '500:内部服务器错误' message = '501:服务未实现' message = '502:网络错误' message = '503:服务不可用' message = '504:网络超时' message = '505:HTTP版本不受支持'
本人前端小菜鸡,如有不对请谅解 - 码表示服务器在尝试处理请求时发生内部错误。