Ajax

Ajax

Ajax就是异步的JS和XML

  • Ajax的一个最大的特点就是无需刷新页面便可向服务器传输或读写数据(又称无刷新更新页面),这一特点主要得益于XMLHTTP组件XMLHttpRequest对象。

  • 在不刷新页面的情况下,向服务器发送请求,获取数据进行处理。

  • 核心:XMLHttpRequest对象,提供发送HTTP请求和接收响应的功能,除此之外,还可以使用jQuery等JavaScript库中提供的Ajax方法、Fetch API等技术实现Ajax功能。

异步请求和同步请求:

  • 异步请求:在发请求之后,其他的同步任务都已经执行完毕。
  • 同步请求:在发送请求之后,需要等到响应完全结束之后才会执行剩下同步任务。
  • 默认情况 ajax发送的都是异步请求 通过open方法的第三个参数可以设置同步。
    • true 表示异步请求 默认的
    • false 表示同步请求 一般不用

1. Ajax经典四步

  1. 创建ajax对象
let xhr = new XMLHttpRequest();
  1. 监听成功的响应--服务器响应了数据,就会触发load事件
xhr.onload = () => {
    // xhr.responseText 得到服务器响应过来的数据
    console.log("接收到响应据:",xhr.responseText);
}
  1. 设置请求(配置网络请求)

    有三个参数

    参数一: 请求方式 get , post , put , delete , head ......

    参数二: 请求的API (URL-http://127.0.0.1:3000/getData)

    参数三: 是否异步(true,false)

xhr.open('get','http://127.0.0.1:3000/getData')
  1. 发出请求

    可以给服务器传递数据 send(请求体)

xhr.send()

2. 通过url把数据传给服务器

关键:

get请求只能通过url把数据传给服务器

在配置网络请求open()中,通过 拼接查询字符串?拼接

关键代码:

let msg = `userName=${userName.value}&pwd=${pwd.value}`
xhr.open('get','/getData?'+msg)
  • 前端结构如下
<h1>通过url把数据扔给服务器</h1>
  <hr>
  <table>
    <tr>
      <td>用户名:</td>
      <td><input type="text" name="username" id="username"></td>
    </tr>
    <tr>
      <td>密码:</td>
      <td><input type="password" name="pwd" id="pwd"></td>
    </tr>
    <tr>
      <td></td>
      <td>
        <button id="btn">GET方式提交</button>
      </td>
    </tr>
  </table>
  • js代码如下
let btnEle = document.querySelector('#btn')
let userName = document.querySelector('#username')
let pwd = document.querySelector('#pwd')

let xhr = new XMLHttpRequest()

xhr.onload = () => {
  console.log(xhr.responseText);
}

btnEle.onclick = () => {
  // 拼接查询字符串?
  let msg = `userName=${userName.value}&pwd=${pwd.value}`
  // get请求只能通过url把数据传给服务器
  xhr.open("get",'/getData?'+msg)
  xhr.send()
}

3. 通过请求体把数据传给服务器

关键:

post、put请求不仅能通过url给服务器传递数据

还可以通过请求体把数据传给服务器 send(请求体)

请求体中有多种格式

  • text/plain

    默认的请求体类型,如果不设置请求头字段Content-Type,请求体只要是字符串就行,传递的数据形式为x=1&y=2,后端不做任何处理,如后端得到的数据为 x=1&y=2

    前端结构如下:

    <h1>通过post把数据扔给服务器</h1>
      <hr>
      <table>
        <tr>
          <td>用户名:</td>
          <td><input type="text" name="username" id="username"></td>
        </tr>
        <tr>
          <td>密码:</td>
          <td><input type="password" name="pwd" id="pwd"></td>
        </tr>
        <tr>
          <td></td>
          <td>
            <button id="btn">POST方式提交</button>
          </td>
        </tr>
      </table>
    

    js代码如下:

    let btn = document.querySelector('#btn')
    let username = document.querySelector('#username')
    let pwd = document.querySelector('#pwd')
    
    let xhr = new XMLHttpRequest()
    xhr.onload = () => {
      console.log(xhr.responseText);
    }
    
    btn.onclick = function () {
      xhr.open('post','/postData')
      let msg = `username=${username.value}&pwd=${pwd.value}`
      // send中写请求体   称为请求体传参
      xhr.send(msg)
    }
    
  • x-www-form-urlencoded

    在发送请求之前,设置请求头字段Content-Type, 一定要在open()之后send()之前

    传递的数据形式为 x=1&y=2 , 后端接收到的数据类型是一个对象

    关键代码:

    let msg = `username=${username.value}&pwd=${pwd.value}`
    xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
    

    前端结构如下:

    <h1>通过post把数据扔给服务器</h1>
      <hr>
      <table>
        <tr>
          <td>用户名:</td>
          <td><input type="text" name="username" id="username"></td>
        </tr>
        <tr>
          <td>密码:</td>
          <td><input type="password" name="pwd" id="pwd"></td>
        </tr>
        <tr>
          <td></td>
          <td>
            <button id="btn">POST方式提交</button>
          </td>
        </tr>
      </table>
    

    js代码如下:

    const btn = document.querySelector('#btn');
    const username = document.querySelector('#username');
    const pwd = document.querySelector('#pwd');
    
    let xhr = new XMLHttpRequest()
    xhr.onload = () => {
      console.log(xhr.responseText);
    }
    
    btn.onclick = function () {
      xhr.open('post','/postData')
      let msg = `username=${username.value}&pwd=${pwd.value}`
    
      // 在发送请求之前,设置请求头 设置的叫Content-Type
      // 请求头一定要在open之后 send之前
      xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
    
      xhr.send(msg)
    
    }
    
  • json

    在发送请求之前,设置请求头字段Content-Type, 一定要在open()之后send()之前

    传递的数据形式为{x:1,y:2} 不用通过& 但是传递时需要手动转为JSON字符串

    后端接收到的数据类型是一个对象

    关键代码:

    let msg = { username: username.value, pwd: pwd.value }
    xhr.setRequestHeader('Content-Type', 'application/json')
    xhr.send(JSON.stringify(msg))
    

    前端结构如下:

    <h1>通过post把数据扔给服务器</h1>
      <hr>
      <table>
        <tr>
          <td>用户名:</td>
          <td><input type="text" name="username" id="username"></td>
        </tr>
        <tr>
          <td>密码:</td>
          <td><input type="password" name="pwd" id="pwd"></td>
        </tr>
        <tr>
          <td></td>
          <td>
            <button id="btn">POST方式提交</button>
          </td>
        </tr>
      </table>
    

    前端js如下:

    const btn = document.querySelector('#btn');
    const username = document.querySelector('#username');
    const pwd = document.querySelector('#pwd');
    
    let xhr = new XMLHttpRequest();
    
    xhr.onload = () => {
      console.log(xhr.responseText);
    }
    
    btn.onclick = () => {
      xhr.open('post', '/postData')
        
      // 如果请求体格式为json 就不用通过 x=y&z=s
      let msg = { username: username.value, pwd: pwd.value }
    
      // 设置请求头一定要在open之后 send之前
      xhr.setRequestHeader('Content-Type', 'application/json')
    
      // 传递时 需要手动转化成JSON字符串
      xhr.send(JSON.stringify(msg))
    }
    
  • 以上不论以哪种形式传递,传递时都是字符串

    • text/plain 后端不会解析成对象
    • application/x-www-form-urlencoded 后端解析为对象
    • application/json 后端解析为对象 但传递时要手动序列化

4. 表单默认发送请求(非Ajax)

  • 表单默认请求的请求类型为document
  • 直接表单请求整体网页会刷新
  • 请求头格式为x-www-form-urlencoded (不用设置,默认此格式)

前端结构如下:

<h1>表单默认发送请求</h1>
    <hr>
    <form action="/postData?a=1&b=2" method="post">
        <table>
            <tr>
                <td>用户名:</td>
                <td><input type="text" name="username" id="username"></td>
            </tr>
            <tr>
                <td>密码:</td>
                <td><input type="password" name="pwd" id="pwd"></td>
            </tr>
            <tr>
                <td></td>
                <td>
                    <input type="submit" value="非ajax请求"></input>
                </td>
            </tr>
        </table>
    </form>

5. 通过FormData传递数据

  • form表单有默认的提交刷新页面事件
  • onsubmit=‘return false’ 阻止提交默认事件

关键:

  • 创建一个FormData容器,直接在请求体中放该容器send(容器)

  • 关于容器的数据添加

    • 方式一:创建FormData容器,通过append()方法添加

      let fd = new FormData()
      fd.append('username',username.value)
      fd.append('password',pwd.value)
      fd.append('id','001')
      
    • 方式二:获取formDOM元素,创建FormData容器将元素添加到FormData中

      let formEle = document.querySelector("form")
      let fd = new FormData(formEle)
      
    • 文件的上传

      <input type="file" name="avator" id="avator">

      const avator = document.querySelector("#avator")

      let fd = new FormData()
      fd.append("avator", avator.files[0]);
      
  • 既可以传递数据 也可以传递文件

前端结构如下:

<form onsubmit="return false">
    <table>
      <tr>
        <td>用户名:</td>
        <td><input type="text" name="username" id="username"></td>
      </tr>
      <tr>
        <td>密码:</td>
        <td><input type="password" name="pwd" id="pwd"></td>
      </tr>
      <tr>
        <td>头像: </td>
        <td><input type="file" name="avator" id="avator"></td>
      </tr>
      <tr>
        <td></td>
        <td>
          <button id="btn1">提交1</button>
        </td>
      </tr>
    </table>
</form>

前端js如下:

const username = document.querySelector("#username")
const pwd = document.querySelector("#pwd")
const btn1 = document.querySelector("#btn1")
const avator = document.querySelector("#avator")

const xhr = new XMLHttpRequest();

xhr.onload = () => {
  alert(xhr.responseText);
};


btn1.onclick = () => {
  // 方式一
  // let fd = new FormData();
  //       fd.append("username",username.value)
  //       fd.append("pwd",pwd.value)
  //       fd.append("aaaa",1111)
  //       fd.append("bbbb",2222)

  // 方式二
  // let formBox = document.querySelector("form");
  // let fd = new FormData(formBox);

  // 传文件
  const fd = new FormData();
  fd.append("uname", username.value);
  fd.append("upwd", pwd.value);
  fd.append("avator", avator.files[0]);

  xhr.open('POST', '/upload');
  xhr.send(fd);
}

6. 响应报文

后端响应给前端的东西 格式:xhr.xxx

  • 响应行
    • status 响应状态码
    • statusText 响应状态码描述
  • 响应头
    • getResponseHeader("XXXXXX") 获取对应字段内容
    • getAllResponseHeaders() 获取响应头全部内容
  • 响应体
    • response 服务器的响应
    • responseText 服务器的响应 返回数据的文本

7. 响应JSON

  • 在前端设置期望响应的数据类型,期望服务器响应json
xhr.responseType = 'json'
// 当设置响应类型为json后,xhr.responseText不能使用
  • 服务端可以设置响应头字段,告诉客户端响应的是JSON数据
let score = [1,2,3]
let scoreJson = JSON.stringify(score)
res.setHeader("Content-Type","application;charset=utf-8")
res.send(scoreJson)

8. 超时处理

  • 自动取消请求,设置时间,时间到了数据还没有响应回来
xhr.timeout = 3000
  • 手动取消请求
xhr.abort()

9. Ajax中的事件

  • onreadystatechange

    • 当ajax请求状态发生变化触发
    • readyState === 4 等价于load事件
    readyState === 0 : xhr对象已创建或已被abort()方法重置
    readyState === 1 : open()方法被调用
    readyState === 2 : send()方法被调用 并且响应头和响应状态可获得
    readyState === 3 : 下载中,正在解析响应内容
    readyState === 4 : 响应内容接收完毕
    
  • onloadstart

    • 开始发送请求触发
    • 此时readyState === 1
  • onload

    • 数据接收完毕触发
  • onerror

    • 请求失败触发 -- 请求发不出去 (404表示请求成功)
  • onprogress

    • 接收响应数据时,周期性触发,直到接收完毕
    • 传参e事件对象
    • e.loaded 已经接收的数据
    • e.total 总的数据
  • onloadend

    • 不论成败 最后都触发

10. 总结

属性 含义
readyState 表示响应的状态 返回一个数字
status 响应状态码 200 400 等
statusText 响应状态码对应描述 200--OK
responseXML 接收格式为XML格式,返回一个document对象
responseType 设置响应内容的类型
response 返回的类型取决responseType的设置
responseText 返回数据的文本
timeout 超时时间
方法 描述
open() 初始化HTTP请求,指定请求方式和URL
send() 向服务器发送请求,参数可设置请求体
abort() 若请求已发出,立即终止当前请求
setRequestHeader() 设置HTTP请求头的值,必须在open()之后
getResponseHeader() 返回指定的响应头
getAllResponseHeaders() 返回所有的响应头
事件 触发条件
readystatechange readyState属性值改变触发
loadstart 接收到响应数据时触发
load 请求完成触发
error 请求遇到错误触发
progress 接收到更多数据时,周期性触发
loadend 请求结束触发,无论成败
timeout 预设时间内没有接收到响应触发
posted @ 2024-04-16 22:12  sunxyrise  阅读(39)  评论(0)    收藏  举报