Ajax详解

Ajax

Ajax 全称是 asynchronous javascript and xml,并不是新的编程语言,可以说是已有技术的组合,主要用来实现客户端与服务器端的异步通信效果,实现页面的局部刷新,从而创建快速动态网页的技术。

Ajax过程

-  创建XMLHttpRequest对象,也就是创建一个异步调用对象
-  创建一个新的HTTP请求,并指定其请求的方法、URL及验证信息
-  设置响应 HTTP 请求状态变化的函数
-  发送 HTTP 请求
-  获取异步调用返回的数据
-  使用 JavaScript 和 DOM 实现局部刷新
var xhr = null; // 创建异步对象
if(window.XMLHttpRequest){
  xhr = new XMLHttpRequest(); // ie7+等现代浏览器
}else if(window.ActiveXObject){ // ie6,老版Opera
  xhr = new ActiveXObject('Microsft.XMLHTTP');
}
xhr.open('get','http://localhost:4000/test',true); // true是异步,可省略
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // post 必须设置
xhr.onreadystatechange = function(){ // 若为同步,此代码不用写,直接在send后,用`xhr.responseText`即可。
    if(xhr.readyState==4 && xhr.status==200){
    /* 
    readyState
        0: 请求未初始化
        1: 服务器连接已建立
        2: 请求已接收
        3: 请求处理中
        4: 请求已完成,且响应已就绪
    status
        200 OK
        404 Not Found
    */
      xhr.responseText;
      xhr.responseXML.children[0].children;
      JSON.parse(xhr.responseText);
    }
}
xhr.send(String); // 用于post传参,形式:"a=1&b=2",而get传参就在url后面用“?”拼接

优缺点

  • 优点:可以使得页面不重载全部内容的情况下加载局部内容,降低数据传输量,避免用户不断刷新或者跳转页面,提高用户体验
  • 缺点:对搜索引擎不友好,要实现ajax下的前进后退功能成本较大;跨域问题限制

jQuery 中的 Ajax

全局ajax事件处理器

jQuery 库支持完整的 Ajax 操作。这里所包含的所有函数和方法用于从服务端加载数据,并且不会导致页面刷新

  • $(document).ajaxComplete(handler(event, XMLHttpRequest, ajaxOptions)) 当Ajax请求完成后注册一个回调函数。

    • 每当一个Ajax请求完成,jQuery就会触发ajaxComplete事件,在这个时间点所有处理函数会使用.ajaxComplete()方法注册并执行。
    • 从 jQuery 1.8 开始, .ajaxComplete() 方法只能绑定到 document元素。
    • 如果global选项设置为false,调用$.ajax() 或 $.ajaxSetup(),.ajaxComplete()方法将不会被触发。
  • 类似的还有:请求出错ajaxError()、请求发送前ajaxSend()、请求刚开始ajaxStart()、请求完成时ajaxStop()、请求成功完成时ajaxSuccess()

辅助函数

  • $.param() 创建一个数组或对象序列化的字符串,适用于一个URL地址查询字符串或Ajax请求。此方法无法对复杂数据结构进行编码。
  • serialize() 将用作提交的表单元素的值编译成字符串。
<form action="#">
    <input name="username" value="abc">
    <input name="age" value="24">
    <select name="sex">
        <option value="0">女</option>
        <option value="1">男</option>
    </select>
    <input type="submit" value="提交">
</form>

console.log($("form").serialize()); // username=abc&age=24&sex=0
  • serializeArray() 将用作提交的表单元素的值编译成拥有name和value对象组成的数组。

console.log($("form").serializeArray()); // [{name: "username", value: "abc"}, {name: "age", value: "24"}, {name: "sex", value: "0"}]

底层接口

  • $.ajax(url, {})$.ajax({url: ""}) 关于传参项(可以使用$.ajaxSetup()设置任何默认参数),下面列举一些常用的:

    • url:String,一个用来包含发送请求的URL字符串
    • data:Object、String,发送到服务器的数据。将自动转换为请求字符串格式。GET 请求中将附加在 URL 后面。
    • dataType:String,默认Intelligent Guess (xml, json, script, or html))。预期服务器返回的数据类型。

      • xmlhtmlscriptjsontext
      • jsonp: 以 JSONP 的方式载入 JSON 数据块。会自动在所请求的URL最后添加 "?callback=?"。默认情况下不会通过在URL中附加查询字符串变量 "_=[TIMESTAMP]" 进行自动缓存结果,除非将 cache参数设置为true。
    • accepts:PlainObject(可用$.isPlainObject()检测),内容类型发送请求头(Content-Type),用于通知服务器该请求需要接收何种类型的返回结果。如果accepts设置需要修改,推荐在$.ajaxSetup() 方法中设置一次。
    • async:Boolean,默认true,异步请求
    • global:Boolean,默认true。该请求是否触发全局处理事件(如$(document).ajaxComplete()等)
    • beforeSend(jqXHR, settings):Function,请求发送前的回调函数,用来修改请求发送前jqXHR,此功能可用来设置自定义 HTTP 头信息,在beforeSend函数中返回false将取消这个请求。
    • catch:Boolean,默认true,dataType为"script"和"jsonp"时默认为false。是否缓存此页面,原理是在GET请求参数中附加"_=时间戳"。该参数不是其他请求所必须的,除了在IE8中,当一个POST请求一个已经用GET请求过的URL。
    • complete:Function,请求完成后回调函数 (请求success 和 error之后均调用)。
    • success(data, textStatus, jqXHR):Function,请求成功时调用函数
    • error:Function,请求失败时调用函数
    • timeout:Number,设置请求超时时间(毫秒)。此设置将覆盖$.ajaxSetup() 里的全局设置。
    • jsonp:String,在一个jsonp请求中重写回调函数的名字。这个值用来替代在"callback=?"这种GET或POST请求中URL参数里的"callback"部分,比如{jsonp:'onJsonPLoad'}会导致将"onJsonPLoad=?"传给服务器。在jQuery 1.5,,设置jsonp选项为false,阻止了jQuery从加入"?callback"字符串的URL或试图使用"=?"转换。在这种情况下,你也应该明确设置jsonpCallback设置。例如, { jsonp: false, jsonpCallback: "callbackName" }
    • jsonpCallback:String、Function,为jsonp请求指定一个回调函数名。这个值将用来取代jQuery自动生成的随机函数名。这主要用来让jQuery生成一个独特的函数名,这样管理请求更容易,也能方便地提供回调函数和错误处理。你也可以在想让浏览器缓存GET请求的时候,指定这个回调函数名。从jQuery 1.5开始,你也可以使用一个函数作为该参数设置,在这种情况下,该函数的返回值就是jsonpCallback的结果。
    • contents: PlainObject,一个以"{字符串/正则表达式}"配对的对象,根据给定的内容类型,解析请求的返回结果。
    • contentType:String,默认application/x-www-form-urlencoded; charset=UTF-8。发送信息至服务器时内容编码类型。
    • context:Object,设置Ajax相关回调函数的上下文。即改变回调函数的this,默认就是传入的整个对象。
    • converters: PlainObject,默认: {"* text": window.String, "text html": true, "text json": jQuery.parseJSON, "text xml": jQuery.parseXML}。一个数据类型到数据类型转换器的对象。每个转换器的值是一个函数,返回经转换后的请求结果。
    • crossDomain:Boolean,同域请求为false, 跨域请求为true。如果你想在同一域中强制跨域请求(如JSONP形式),例如,想服务器端重定向到另一个域,那么需要将crossDomain设置为 true 。
    • username:String,于响应HTTP访问认证请求的用户名
    • password:String,用于响应HTTP访问认证请求的密码
  • $.ajax() 返回jqXHR对象,可调用

    • .done() success
    • .fail() error
    • .always() complete
    • .then() 传两个回调函数,分别是done和fail
  • $.ajaxPrefilter([dataTypes], handler(options, originalOptions, jqXHR) ) 在每个请求之前被发送和$.ajax()处理它们前处理,设置自定义Ajax选项或修改现有选项。
  • $.ajaxSetup(options) 为以后要用到的Ajax请求设置默认的值,其后的 AJAX 请求不再设置任何已设置的选项参数。

快捷方法

  • $.get() {type: "get"}
  • $.post() {type: "post"}
  • $.getScript() {type: "script"}
  • $.getJSON() {type: "json"}
  • $(selector).load() 从服务器载入数据并且将返回的 HTML 代码并插入至 匹配的元素中。

jQuery中jsonp

// 前端
function jsonpFn(data){
    console.log(data)
    console.log("jsonpFn");
}
$(function(){
    $.ajax({
        url: "http://localhost:3000/test",
        data: {username: "xx"},
        dataType: "jsonp",
        jsonp: "selfNamedReplaceCallback",
        jsonpCallback: "jsonpFn", // server side:req.query.callback = "jsonpFn"
        success(data){
            console.log(data)
        }
    })
})

// 后端
const app = require('express').Router();
app.get('/test', (req, res, next) => {
    let name = req.query.username;
    let callback = req.query.selfNamedReplaceCallback
    let s1 = "{status: 1}"
    let s2 = `
        {
            status: 0,
            info: {
                name: "${name}",
                age: 24,
                sex: "girl",
                tel: "1522*******"
            }
        }
    `
    s1=callback+"("+s1+")"
    s2=callback+"("+s2+")"
    if(!name)return res.send(s1)
    res.send(s2)
}).listen(3000)

Axios

  • axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。
  • 从浏览器中创建 XMLHttpRequests
  • 从 node.js 创建 http 请求
  • 支持 Promise API
  • 拦截请求和响应
  • 转换请求数据和响应数据
  • 取消请求
  • 自动转换 JSON 数据
  • 客户端支持防御 XSRF

在vue项目中使用axios 的 Demo

// main.js
import axios from 'axios'
axios.defaults.baseURL = 'http://localhost/'
Vue.prototype.$axios = axios
// 在 .vue 文件(组件)
this.$axios.get("").then().catch()

this.$axios.all([
    this.$axios.post('one','content=123'),
    this.$axios.get('one?pageIndex=1')
])
.then(this.$axios.spread((res1,res2)=>{
    console.log(res1,res2)
}))
.catch(err=>{
    console.log(err)
})

这里分发请求,同时请求成功才执行 then 方法,可用于获取 省市区 的数据

// 在 server.js 文件
const Koa = require('koa')
const Router = require('koa-router')
const app = new Koa()
const router = new Router()
router.get('/one',ctx=>{
    ctx.body = {
        a: 1,
        b: 2
    }
})
router.post('/one',ctx=>{
    ctx.body = {
        c: 3,
        d: 4
    }
})

app.use((ctx,next)=>{
    ctx.set("Access-Control-Allow-Origin", "*");
    ctx.body = {}
    next()
})
.use(router.routes())
.use(router.allowedMethods())
.listen(80)
拦截器
axios.interceptors.request.use(function(ops){
    console.log(ops);
    ops.headers = {/* ... */}; // 请求前修改
    return ops; // 返回没有修改的位置,如果return false 直接拦截
})

例如,在请求成功前显示加载loading图标,拿到数据后消失

// main.js
import Mint from 'mint-ui' // 实际项目中选择引入
import 'mint-ui/lib/style.css'
Vue.use(Mint)

axios.interceptors.request.use(function(config){
    Mint.Indicator.open()
    return config;
})
axios.interceptors.response.use(function(data){
    Mint.Indicator.close()
    return data;
})

Ajax、jQuery.ajax、Axios和Fetch的区别

  • ajax最早出现的发送后端请求技术,利用用XMLHttpRequest对象。
  • $.ajax是jQuery中的发送后端请求技术,基于原生Ajax的封装。
  • Axios不是原生JS的,需要进行安装。它在client-side和server-side都可以使用。也可以在请求和响应阶段进行拦截。它是基于promise对象的。
  • Fetch号称是AJAX的替代品,使用了ES6中的promise对象。其参数有点像jQuery.ajax。但是fetch不是对ajax的封装,而是原生js实现的,并没有使用XMLHttpRequest对象。
188 声望
4 粉丝
0 条评论
推荐阅读
useReducer + useContext + createContext
把CounterContext.Provider抽成组件拿出来 {代码...} 把组件分一下文件就是index.jsx {代码...} comA.jsx {代码...} comB.jsx {代码...}

落霞与孤鹜齐飞阅读 835

ESlint + Stylelint + VSCode自动格式化代码(2023)
安装插件 ESLint,然后 File -&gt; Preference-&gt; Settings(如果装了中文插件包应该是 文件 -&gt; 选项 -&gt; 设置),搜索 eslint,点击 Edit in setting.json

谭光志34阅读 20.9k评论 9

安全地在前后端之间传输数据 - 「3」真的安全吗?
在「2」注册和登录示例中,我们通过非对称加密算法实现了浏览器和 Web 服务器之间的安全传输。看起来一切都很美好,但是危险就在哪里,有些人发现了,有些人嗅到了,更多人却浑然不知。就像是给门上了把好锁,还...

边城32阅读 7.4k评论 5

封面图
涨姿势了,有意思的气泡 Loading 效果
今日,群友提问,如何实现这么一个 Loading 效果:这个确实有点意思,但是这是 CSS 能够完成的?没错,这个效果中的核心气泡效果,其实借助 CSS 中的滤镜,能够比较轻松的实现,就是所需的元素可能多点。参考我们...

chokcoco24阅读 2.3k评论 3

在前端使用 JS 进行分类汇总
最近遇到一些同学在问 JS 中进行数据统计的问题。虽然数据统计一般会在数据库中进行,但是后端遇到需要使用程序来进行统计的情况也非常多。.NET 就为了对内存数据和数据库数据进行统一地数据处理,发明了 LINQ (L...

边城17阅读 2.1k

封面图
过滤/筛选树节点
又是树,是我跟树杠上了吗?—— 不,是树的问题太多了!🔗 相关文章推荐:使用递归遍历并转换树形数据(以 TypeScript 为例)从列表生成树 (JavaScript/TypeScript) 过滤和筛选是一个意思,都是 filter。对于列表来...

边城18阅读 7.9k评论 3

封面图
Vue2 导出excel
2020-07-15更新 excel导出安装 {代码...} src文件夹下新建一个libs文件夹,新建一个excel.js {代码...} vue页面中使用 {代码...} ===========================以下为早期的文章今天在开发的过程中需要做一个Vue的...

原谅我一生不羁放歌搞文艺14阅读 20.1k评论 9

188 声望
4 粉丝
宣传栏