一、XMLHttpRequest概念

1、定义

XMLHttpRequest(简称xhr),是浏览器提供的JS对象,通过它可以请求到服务器上的数据资源

2、能否直接使用xhr对象发起Ajax请求

可以,但比较麻烦
jQuery中的Ajax函数时基于xhr对象封装出来的。

3、什么是Ajax

Ajax是一种用于创建快速动态网页的技术,在网页中利用XMLHttpRequest对象和服务器进行数据交互的方式

二、xhr发起GET请求

步骤:创建xhr对象 → 调用xhr.open()函数 → 调用xhr.send()函数 → 监听xhr.onreadyStatechange事件

1、创建xhr对象

var xhr = new XMLHttpRequest()

2、调用xhr.open()函数

xhr.open(‘请求方式’,‘请求地址’)

xhr.open('get','https://blog.csdn.net/Vest_er/article/details/127216365');

3、调用xhr.send()函数

xhr.send()

4、监听xhr.onreadyStatechange事件

监听xhr对象的请求状态readyState,与服务器响应状态status

xhr.onreadyStatechange = function () {
	// 固定的判断条件
	 if(xhr.readyState) === 4 && xhr.status === 200 {
	 	// 打印服务器响应回来的数据
		console.log(xhr.responseText)
	}
}

5、发送带参数的get请求

通过查询字符串的形式发起带参数请求

xhr.open('get','https://blog.csdn.net/Vest_er?id=02&name=zs');

三、xhr发起POST请求

步骤:创建xhr对象 → 调用xhr.open()函数 → 设置Content-Type属性 → 调用xhr.send()函数 → 监听xhr.onreadyStatechange事件

1、创建xhr对象

var xhr = new XMLHttpRequest()

2、调用xhr.open()函数

xhr.open(‘请求方式’,‘请求地址’)

xhr.open('post','https://blog.csdn.net');

3、设置Content-Type属性(固定写法)

xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')

4、调用xhr.send()函数

同时数据以查询字符串的形式,提交给服务器

xhr.send('name=憨瓜&age=3&sex=公猫已绝育')

4、监听xhr.onreadyStatechange事件

监听xhr对象的请求状态readyState,与服务器响应状态status

xhr.onreadyStatechange = function () {
	// 固定的判断条件
	 if(xhr.readyState) === 4 && xhr.status === 200 {
	 	// 打印服务器响应回来的数据
		console.log(xhr.responseText)
	}
}

四、了解xhr的readyState属性

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

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

五、XMLHttpRequest Level2的新特性

Level2代表的是新版的XMLHttpRequest

旧版xhr缺点

① 只支持文本数据的传输,无法用来读取和上传文件
② 传送和接收数据时,没有进度信息,只能提示有没有完成

xhr Level2新功能

1、可以设置HTTP请求的时限

有时Ajax操作很耗时,而且无法预知要等多久。新版xhr对象增加了timeout属性和timeout事件,可以设置http请求时限

timeout属性:设置超时时间;timeout事件:设置超时之后的回调

// 将最长等待时间设置为3秒,超过时限自动地址http请求
xhr.timeout = 3000;

// timeout事件,设置超时之后的回调函数
xhr.ontimeout = function(event) {
	alert('请求超时了!');
}

2、可以使用FormData对象管理表单数据

Ajax操作往往用来提交表单数据。为了方便表单处理,HTML5新增了一个FormData对象,可以模拟表单操作

① 提交form表单数据

<script>
    // 1.创建一个FormData对象
    var fd = new FormData();

    // 2.为FormData添加表单项
    fd.append('uname','憨瓜');
    fd.append('upwd','123456');

    // 3.创建xhr对象
    var xhr = new XMLHttpRequest();

    // 4.指定球球类型和URL地址
    xhr.open("POST",'http://www.liulongbin.top:3006/api/formdata');

    // 5.直接提交formdata对象,这与提交网页表单的效果一样
    xhr.send(fd);

    // 监听请求状态改变的事件
    xhr.onreadystatechange = function (){
        if(xhr.readyState == 4 && xhr.status == 200) {
            // JSON字符串转化为JS对象
            var result = JSON.parse(xhr.responseText);
            console.log(result)
        }
    }
</script>

在这里插入图片描述

② 获取网页表单的值

<body>
    <form  id="form">
        <input type="text" name="uname" autocomplete="off">
        <input type="password" name="upwd">
        <button type="submit">提交</button>
    </form>

    <script>
        // 1.获取表单元素
        var form = document.querySelector("#form");

        // 2.监听表单元素的submit事件
        form.addEventListener('submit',function(e){
            e.preventDefault(); // 阻止表单默认行为
            //根据form表单创建FormData对象会自动将表单数据填充到FormData对象中
            var fd = new FormData(form);

            var xhr = new XMLHttpRequest();
            xhr.open("POST",'http://www.liulongbin.top:3006/api/formdata');
            xhr.send(fd);

            xhr.onreadystatechange = function (){
                 if(xhr.readyState == 4 && xhr.status == 200) {
            		console.log(JSON.parse(xhr.responseText));
     			 }
            }
        })
    </script>
</body>

在这里插入图片描述

3、 可以上传文件

实现步骤:定义UI结构 → 验证用户是否选择了文件 → 向FornData中追加文件 → 使用xhr发起上传文件的请求 → 监听onreadyStatechange事件

① 定义UI结构

<!--1. 文件选择框 -->
<input type="file" id="file1">
<!-- 2. 上传文件按钮 -->
<button id="btnUpload">上传文件</button><br />
<!-- 3.img标签用来显示上传成功以后的图片 -->
<img src="" id="img" width="800">

② 验证用户是否选择了文件

// 1.获取上传文件的按钮
var btnUpload = document.querySelector('#btnUpload');
// 2. 为按钮绑定单击事件处理函数
btnUpload.addEventListener('click',function(){
    // 3.获取到选择的文件列表
    var files = document.querySelector("#file1").files;
    if(files.length<=0){
        return alert ('请选择要上传的文件');
    }
})

③ 向FormData中追加文件

// 1.创建formdata对象
var fd = new FormData();
// 2.向formdata中追加文件
fd.append("avatar",files[0])

④ 使用xhr发起上传文件的请求

// 1.创建xhr
var xhr = new XMLHttpRequest();
// 2.创建请求
xhr.open("POST",'http://www.liulongbin.top:3006/api/upload/avator');
// 3.发起请求
xhr.send(fd);

⑤ 监听onreadyStatechange事件

xhr.onreadystatechange = function () {
  if (xhr.readyState === 4 && xhr.status === 200) {
    var data = JSON.parse(xhr.responseText)
    if (data.status === 200) {
      // 上传成功
      document.querySelector('#img').src = 'http://www.liulongbin.top:3006' + data.url
    } else {
      // 上传失败
      console.log('图片上传失败!' + data.message)
    }
  }
}

4、可以获得数据传输的进度信息

可以通过监听xhr.upload.onprogress事件,来获取文件的上传进度

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

六、案例(实现文件带进度条上传)

1、基于Bootstrap绘制进度条效果

Bootstrap进度条地址:https://v3.bootcss.com/components/#progress

 <!-- 引入Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">

<!-- bootstrap 中的进度条 -->
<div class="progress" style="width: 500px; margin: 15px 10px;">
  <div class="progress-bar progress-bar-striped active" style="width: 0%" id="percent">
    0%
  </div>
</div>

2、动态设置进度条

基于jQuery操作DOM,调用attr属性设置style样式

引入jQuery
 <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
 
// 监听文件上传的进度
xhr.upload.onprogress = function (e) {
  if (e.lengthComputable) {
    // 计算出上传的进度
    var procentComplete = Math.ceil((e.loaded / e.total) * 100)
    console.log(procentComplete)
    // 动态设置进度条
    $('#percent').attr('style', 'width: ' + procentComplete + '%;').html(procentComplete + '%')
  }
}

3、监听上传完成的事件

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

完整代码

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <!-- 引入bootstrap-->
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
  <!-- 引入jQuery -->
  <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
</head>

<body>
  <!-- 1. 文件选择框 -->
  <input type="file" id="file1" />
  <!-- 2. 上传文件的按钮 -->
  <button id="btnUpload">上传文件</button>

  <!-- bootstrap 中的进度条 -->
  <div class="progress" style="width: 500px; margin: 15px 10px;">
    <div class="progress-bar progress-bar-striped active" style="width: 0%" id="percent">
      0%
    </div>
  </div>

  <br />
  <!-- 3. img 标签,来显示上传成功以后的图片 -->
  <img src="" alt="" id="img" width="800" />

  <script>
    // 1. 获取到文件上传按钮
    var btnUpload = document.querySelector('#btnUpload')
    // 2. 为按钮绑定单击事件处理函数
    btnUpload.addEventListener('click', function () {
      // 3. 获取到用户选择的文件列表
      var files = document.querySelector('#file1').files
      if (files.length <= 0) {
        return alert('请选择要上传的文件!')
      }
      var fd = new FormData()
      // 将用户选择的文件,添加到 FormData 中
      fd.append('avatar', files[0])

      var xhr = new XMLHttpRequest()

      // 监听文件上传的进度
      xhr.upload.onprogress = function (e) {
        if (e.lengthComputable) {
          // 计算出上传的进度
          var procentComplete = Math.ceil((e.loaded / e.total) * 100)
          console.log(procentComplete)
          // 动态设置进度条
          $('#percent').attr('style', 'width: ' + procentComplete + '%;').html(procentComplete + '%')
        }
      }

      xhr.upload.onload = function () {
        $('#percent').removeClass().addClass('progress-bar progress-bar-success')
      }

      xhr.open('POST', 'http://www.liulongbin.top:3006/api/upload/avatar')
      xhr.send(fd)

      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4 && xhr.status === 200) {
          var data = JSON.parse(xhr.responseText)
          if (data.status === 200) {
            // 上传成功
            document.querySelector('#img').src = 'http://www.liulongbin.top:3006' + data.url
          } else {
            // 上传失败
            console.log('图片上传失败!' + data.message)
          }
        }
      }
    })
  </script>
</body>

</html>

最终效果

在这里插入图片描述

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐