推荐使用 Axios

  • Axios 是专注于网络数据请求的库。
  • 相比于原生的 XMLHttpRequest 对象,axios 简单易用
  • 相比于 jQuery,axios 更加轻量化,只专注于网络数据请求。

传统的Ajax (XHR)

基本使用步骤

  1. 创建 xhr 对象

  2. 调用 xhr.open()函数

  • (POST 请求)设置 Content-Type 属性(固定写法)
  1. 调用 xhr.send() 函数

  2. 监听 xhr.onreadystatechange 事件

    GET请求

// 创建 xhr 对象
const xhr = new XMLHttpRequest()
// 调用 open 指定请求方式和 url 地址
// 带有参数可以使用查询字符串格式
// 请求地址URL用 ? 拼接
// 例如 id=1&&page=2
xhr.open('GET','https://www.baidu.com/api?id=1&&page=2')
// 调用 send 发起 Ajax 请求
xhr.send()
// 监听发起请求后的事件,onreadystatechange
xhr.onreadystatechange = function() {
  // 监听
  // 请求对象的请求状态 readyState
  // 服务器响应状态 status
  if(xhr.readyState === 4 && xhr.status === 200){
    // responeseText响应回来的数据
    console.log(xhr.responeseText)
  }
}

POST请求

// // 创建 xhr 对象
const xhr = new XMLHttpRequest()
// 调用 open 指定请求方式和 url 地址
xhr.open('POST','https://www.baidu.com/api')
// 设置 Content-Type 属性(固定写法)
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
// 调用 send(),同时将数据以查询字符串的形式,提交给服务器
xhr.send('id=1&author=fantasy&page=2)
 // 监听发起请求后的事件,onreadystatechange
xhr.onreadystatechange = function() {
  // 监听
  // 请求对象的请求状态 readyState
  // 服务器响应状态 status
if(xhr.readyState === 4 && xhr.status === 200){
   // responeseText响应回来的数据
  console.log(xhr.responeseText)
  }
}

XMLHttpRequest 对象的 readyState 属性,用来表示当前 Ajax 请求所处的状态。每个 Ajax 请求必然处于以下状态中的一个:

状态 描述
0 UNSENT XMLHttpRequest 对象已被创建,但尚未调用 open方法。
1 OPENED open() 方法已经被调用。
2 HEADERS_RECEIVED send() 方法已经被调用,响应头也已经被接收。
3 LOADING 数据接收中,此时 response 属性中已经包含部分数据。
4 DONE Ajax 请求完成,这意味着数据传输已经彻底完成或失败。

设置 HTTP 请求时限

xhr.timeout = 3000
xhr.ontimeout = function(event){
     alert('请求超时!')
 }

设置 http 请求时限,3000毫秒,超时执行 ontimeout 的回调函数

FormDate 对象管理表单数据

基本使用

// 新建 FormData 对象
const fd = new FormDate()
// 添加数据 加入表单项
fd.append('id','12')
fd.append('name','fantasy')

// post 请求直接发送 FormData对象
// ...Ajax请求代码
xhr.send(fd)

获取网页 dom 表单的值

// 获取 dom 表单
const form = document.querySelector('#form')
// 监听表单提交
form.addEventListener('submit', function(e) {
  // 阻止表单默认行为
  e.preventDefault()
  //根据 form 表单创建 FormData 对象,会自动将表单数据填充到 FormData 对象中
  const fd = new FormData(form)
 // post 请求直接发送 FormData对象
 // ...Ajax请求代码
 xhr.send(fd)
}

上传文件

 // 1. 创建 FormData 对象
 var fd = new FormData()
 // 2. 向 FormData 中追加文件
 fd.append('avatar', files[0])
 // post 请求直接发送 FormData对象
 // ...Ajax请求代码
 xhr.send(fd)

监听 xhr.upload.onprogress 文件的上传进度

xhr.upload.onprogress = function(e) {
    // e.lengthComputable 是一个布尔值,表示当前上传的资源是否具有可计算的长度
    if (e.lengthComputable) {
        // e.loaded 已传输的字节
        // e.total  需传输的总字节
        const percentComplete = Math.ceil((e.loaded / e.total) * 100)
    }
 }

监听 xhr.upload.onload 文件上传完成

 xhr.upload.onload = function() {
     $('#percent')
         // 移除上传中的类样式
         .removeClass()
         // 添加上传完成的类样式
         .addClass('progress-bar progress-bar-success')
 }

jQuery-Ajax

浏览器中提供的 XMLHttpRequest 用法比较复杂,所以 jQuery 对 XMLHttpRequest 进行了封装,提供了一系列 Ajax 相关的函数,极大地降低了 Ajax 的使用难度。

常用方式

$.get()

$.get(url,[data],[callback])
参数名 参数类型 是否必选 说明
url string 请求的地址
data object 请求传递的参数
callback function 请求成功的回调函数
// 例子
$.get('http://www.badui/api',{id:1,name:'fantasy'}, function(res) {
   // 这里的 res 是服务器返回的数据
  console.log(res) 
})

$.post()

$.post(url,[data],[callback])
参数名 参数类型 是否必选 说明
url string 请求的地址
data object 请求传递的参数
callback function 请求成功的回调函数
// 例子
$.post('http://www.badui/api',{id:1,name:'fantasy'}, function(res) {
   // 这里的 res 是服务器返回的数据
  console.log(res) 
})

$.ajax()

$.ajax({
   type: '', // 请求的方式,例如 GET 或 POST
   url: '',  // 请求的 URL 地址
   data: { },// 这次请求要携带的数据
   success: function(res) { } // 请求成功之后的回调函数
})
// 例子
$.ajax({
   type: 'get', // 请求的方式,例如 GET 或 POST
   url: 'http://www.badui/api',  // 请求的 URL 地址
   data: {id:1,name:'fantasy' },// 这次请求要携带的数据
   success: function(res) { } // 请求成功之后的回调函数
})

FormDate 对象管理表单数据也适合 jQuery-Ajax
因为 FormDate 是 HTML5 新增的一个 对象,可以模拟表单操作
用法大致相同

拼接请求的根路径

建议新建 baseAPI.js

// 注意:每次调用 $.get() 或 $.post() 或 $.ajax() 的时候,
// 会先调用 ajaxPrefilter 这个函数
// 在这个函数中,可以拿到我们给Ajax提供的配置对象
$.ajaxPrefilter(function(options) {
  // 在发起真正的 Ajax 请求之前,统一拼接请求的根路径
  options.url = 'http://ajax.frontend.itheima.net' + options.url
})

统一为有权限的接口设置headers请求头

// 统一为有权限的接口,设置 headers 请求头 
if (options.url.indexOf('/my/') !== -1) { 
 options.headers = { 
  Authorization: localStorage.getItem('token') || '' 
 }
 }
// 全局统一挂载 complete 回调函数
// 不论请求成功还是失败,最终都会调用 complete 回调函数
options.complete = function(res) {
    // 在 complete 回调函数中,可以使用 res.responseJSON 拿到服务器响应回来的数据
    if (res.responseJSON.status === 1 && res.responseJSON.message === '身份认证失败!') {
      // 1. 强制清空 token
      localStorage.removeItem('token')
      // 2. 强制跳转到登录页面
      location.href = '/login.html'
    }
  }

Axios

axios.get

// 语法
axios.get('url',{params:{ 参数 } } ).then(callback)
// 例子
axios.get('url', {
  params :{
      id: 1,
     name:'fantasy'
 }  //res.data 是服务器返回的数据
}).then(res => { consloe.log(res.data) })
参数名 参数类型 是否必选 说明
url string 请求的地址
params object 请求传递的参数
callback function 请求成功的回调函数

axios.post

// 语法
axios.post('url',{ 参数 } ).then(callback)
// 例子
axios.post('url', {
  id:1,
  name:'fantasy'
}).then(res => { consloe.log(res.data) })
//res.data 是服务器返回的数据

axios

// 语法
axios({
// 使用 method 或 type 其中一种声明类型即可
  method/type:'请求类型',
  url:'请求地址',
  data:{ post 数据 },
  params:{ get 参数}
}).then(callback)
// 例子
axios({
  method:'get',
  url:'url',
  params:{id:1,name:'fantasy'}
}).then(res => { consloe.log(res.data) })

配合 async / await 使用

axios返回的数据是一个Promise实例对象,用 .then()取到正确的数据

  • async 关键字用于函数上(async函数的返回值是Promise实例对象)
  • await 关键字用于 async 函数当中(await可以得到异步的结果)
// post 请求例子
document.querySelector('#btnPost').addEventListener('click', async function () {
  // 如果调用某个方法的返回值是 Promise 实例,则前面可以添加 await!
  // await 只能用在被 async “修饰”的方法中
  // 解构赋值 把 axios 返回部分 解构出 data 重命名为 res
  const { data: res } = await axios({
    method: 'POST', 
    url: '/api/post',
    data: {
      name: 'fantasy',
      id: 1
    }
  })

  console.log(res)
})

vue 2.x 全局配置 axios

优点:每个组件可以通过 this.$http.get 直接发起请求,无需再导入 axios ;若根路径发生改变,只需修改 axios.defaults.baseURL ,有利于代码维护。

// main.js
// 配置请求根路径
axios.defaults.baseURL = 'http://api.com'

// 把 axios 挂载到 Vue 原型上
Vue.prototype.$http = aixos

缺点:无法实现 API 的复用。即多个组件需要对同一个接口发起请求,那么每个组件都需要重复书写 this.$http.get('/users') 类似的代码,造成冗余

改进:对于每一个根路径,独立封装一个 request.js 模块,组件导入所需根路径对应的 axios 进行使用

import axios from 'axios'

// 调用 axios.craete() 函数,request 接收 axios 实例对象
const request = axios.create({
  baseURL: 'http://api.com'
})
export default request