AJAX和axios的简单使用

89 阅读11分钟

AJAX

一、同步、异步

1、同步

代码按照顺序执行、立马获得结果就是同步,大多数代码都是同步的

2、异步

代码不一定按照顺序执行,执行后可能需要等待才会返回结果,比如定时器、promise等

二、服务器

服务器的本质:也是一台电脑。 服务器的作用: 存储一个网站的文件(HTML、CSS、JS、图片、音乐.....) 提供网站的文件给用户

资源

服务器上的 网页(html文件)、图片、音乐、视频、字体文件、CSS文件、JS文件等等都称之为资源。所以资源代指服务器上存储的内容。 通俗的讲,我们浏览网页时,从网络当中看到的内容都叫做资源。

三、客户端

概念:在前端开发中,客户端特指“Web 浏览器”。 作用:将互联网世界中的 Web 资源加载、并呈现到浏览器窗口中供用户使用。

URL地址(统一资源定位符)

URL 地址,表示服务器上每个资源的确切位置。

客户端与服务器通信的过程

客户端与服务器之间的通信过程,分为请求 - 响应两个步骤。 请求的概念:客户端通过网络去找服务器要资源的过程,叫做“请求” 响应的概念:服务器把资源通过网络发送给客户端的过程,叫做“响应” image.png

四、什么是AJAX

Ajax 是浏览器中的技术:用来实现客户端网页请求服务器的数据。 它的英文全称是 Asynchronous Javascript And XML,简称 Ajax。

image.png

使用 Ajax 请求数据的 5 种方式

序号请求方式描述
1POST向服务器新增数据
2GET从服务器获取数据
3DELETE删除服务器上的数据
4PUT更新服务器上的数据(侧重于完整更新:例如更新用户的完整信息)
5PATCH更新服务器上的数据(侧重于部分更新:例如只更新用户的手机号)

五、利用axios库发请求

操作服务器上的数据除了要使用 URL地址,还需要指定 请求方式

操作服务器上的数据时: 获取服务器上的数据,需要使用 get 方式 新增(添加)数据,需要使用 post 方式 删除数据,需要使用 delete 方式 完整修改(更新)数据,需要使用 put 方式 修改(更新)部分数据,需要使用 patch 方式

语法:

axios({
  method: '请求的类型',
  url: '请求的URL地址',
   // 查询携带参数
  // 也可以写在url后面
  // http://api/getbooks?参数1=值&参数2=值
  params:{
        
  }
}).then((result) => {
  // then 用来指定请求成功之后的回调函数
  // 形参中的 result 是请求成功之后的结果
})

简写

axios.get()   直接发送get请求
axios.post()  直接发送post请求
axios.delete()   直接发送delete请求
axios.put()    直接发送put请求
axios.patch() 直接发送patch请求

1、get

    axios.get('接口地址', {
      params: {
        appkey: 'hwx123'
      }
    }).then(result => {
      console.log(result);
    })

2、post

axios.post('接口地址', {
      bookname: 'post请求1',
      author: 'post请求222',
      publisher: 'post请求33',
      appkey: 'hwx123',
    }).then(result => {
      console.log(result);
    })
​
    // 2、
    axios.post('接口地址','bookname=111222&author=222222&publisher=33333&appkey=hwx123').then(result => {
      console.log(result);
    })

六、利用axios库增加数据

语法:

axios({
  method: 'POST',
  url: '接口地址',
  // 请求体
  data: {
    bookname: '水浒传',
    author: '施耐庵',
    publisher: '顺义出版社'
  }
}).then(result => {
  console.log(result)
})
​

post请求传参格式

    axios({
        method: 'post',
        url: '接口地址',
        data:'bookname=从入门到精通&author=我自己&publisher=出版社&appkey=hwx123'
        /* data: {
          bookname: '从入门到精通',
          author: '我自己',
          publisher: '出版社',
          appkey: 'wanshao1234',
        }, */
      }).then((result) => {
        console.log(result);
      });

七、利用axios库编辑数据

在按钮设置自定义属性,根据自定义属性的值来编辑

语法:

<script>
    // 根据数组下标修改
    const tbody = document.querySelector('tbody')
    const booknameValue = document.querySelector('.bookname')
    const authorValue = document.querySelector('.author')
    const publisherValue = document.querySelector('.publisher')
​
    let arr = []
    let id // 数组索引
    const btn = document.querySelector('button')
    tbody.addEventListener('click', function (event) {
      if (event.target.nodeName === 'A') {
        id = event.target.dataset.index
        getIdData(id)
        function getIdData(id) {
          let IDdata
          const url = '接口地址?id=' + id
          axios.get(url).then(result => {
            arr = result.data.data
            updataList(arr)
          })
        }
​
        // 数据展现在修改列表
        function updataList(arr) {
          booknameValue.value = arr[0].bookname
          authorValue.value = arr[0].author
          publisherValue.value = arr[0].publisher
        }
      }
    })
    btn.addEventListener('click', function () {
      const url = 'http://www.itcbc.com:3006/api/updatebook'
      const data = {
        id:arr[0].id,
        bookname: booknameValue.value,
        author: authorValue.value,
        publisher: publisherValue.value
      }
      axios.put(url,data).then(result => {
        console.log(result);
        getData()
      })
    })
​
    getData()
    function getData() {
      const url = '接口地址'
      const params = {
        appkey: 'hwx123',
      }
      // 获取数据
      axios.get(url, params).then(result => {
        arr = result.data.data
        render(arr)
      })
    }
​
    function render(arr) {
      let html = arr.map((value, index) => {
        return `
        <tr>
        <td>${value.id}</td>
        <td>${value.bookname}</td>
        <td>${value.author}</td>
        <td>${value.publisher}</td>
        <td><a href='#' data-index='${value.id}'>编辑</a></td>
      </tr>
        `
      }).join('')
      tbody.innerHTML = html
    }
  </script>

八、利用axios库删除数据

把数据id设置在删除按钮上,根据id删除

<script>
    const tbody = document.querySelector('tbody')
    // 输入框的值
    const bookname = document.querySelector('.bookname')
    const author = document.querySelector('.author')
    const publisher = document.querySelector('.publisher')
    // 按钮
    const btn = document.querySelector('button')
    getData()
​
    // 点击新增
    btn.addEventListener('click', function () {
      const title = bookname.value
      const writer = author.value
      const press = publisher.value
      const data = {
        bookname: title,
        author: writer,
        publisher: press
      }
      axios({
        method: 'post',
        url: '接口地址',
        data,
      }).then(result => {
        getData()
        bookname.value = ''
        author.value = ''
        publisher.value = ''
      })
    })
    // 父元素绑定点击事件,利用事件委托
    tbody.addEventListener('click', function (event) {
      console.log(event.target.dataset.index);
      if (event.target.nodeName === 'A') {
        axios({
          method: 'delete',
          url: '接口地址',
          params:{
            id:event.target.dataset.index
          }
        }).then(result => {
          getData()
        })
      }
    })
​
    // 获取数据
    function getData() {
      axios({
        method: 'get',
        url: '接口地址'
      }).then(result => {
        const arr = result.data.data
        render(arr)
      })
    }
​
    // 渲染函数
    function render(arr) {
      let html = arr.map(value => {
        return `
        <tr>
        <td>${value.id}</td>
        <td>${value.bookname}</td>
        <td>${value.author}</td>
        <td>${value.publisher}</td>
        <td><a data-index='${value.id}' class='del' href="#">删除</a></td>
      </tr>`
      }).join('')
      tbody.innerHTML = html
    }
  </script>

九、序列化

把对象或者数组 转成 字符串格式 过程 序列化 JSON.stringify();

把字符串格式 转成 对象或者数组 反序列化 JSON.parse()

1、利用jQuery快速获取表单数据序列化

const data = $('form表单选择器').serialize()

2、自定义快速获取表单数据

获取form表单里,带有name属性的值

const formObj = new FormData(document.querySelector('form'))

处理成 url 上的参数

const usp = new URLSearchParams(data)
const data = {
    bookname: '书名',
    author: '作者',
    publisher: '出版社',
    appkey: 'hwx123',
}
const usp = new URLSearchParams(data)
const str = usp.toString()
// bookname=书名&author=作者&publisher=出版社&appkey=hwx123

十、文件上传

1、input

type = file accept='images/*' 指定图片类型

2、this.files 数组

input.change事件,const file = this.files[0]获取当前文件

获取上传到浏览器的文件地址

const src = URL.createObjectURL(file) // 获取上传到浏览器内存中的文件

3、创建一个formdata对象

const formdata = new FormData()

4、按接口要求添加数据至formdata

formdata.append('avatar',file)
多个数据也一并添加至formdata

5、post发送请求

axios.post('接口地址/api/formdata',formdata).then(result => {
        console.log(result);
      })
<!-- accept="images/*"  指定文件类型 -->
  <input type="file" accept="images/*" multiple> <!-- 此时什么类型都可上传 -->
  <img src="" alt="">
  <script src="./lib/axios.js"></script>
  <script>
    const input =document.querySelector('input')
    const img =document.querySelector('img')
    input.addEventListener('change',function () {
      const file = this.files[0] // 获取当前事件的文件,可以上传多个文件,数组
      console.log(file);
      const src = URL.createObjectURL(file) // 获取上传到浏览器内存中的文件
      img.src = src
      // 接口地址/api/formdata
      // 上传文件,给后端的参数 肯定是 formdata 类型
      const formdata = new FormData() // 创建一个空的formdata对象
      // 接口要求 参数名 avatar  参数类名file
      formdata.append('avatar',file) // 接口要求,把文件追加到formdata对象
      axios.post('接口地址/api/formdata',formdata).then(result => {
        console.log(result);
      })
    })
  </script>

十一、拦截器

分为请求拦截器和响应拦截器

<img src="./images/1.gif" alt="">
  <button>按钮</button>
  <script src="./lib/axios.js"></script>
  <script>
    // 添加请求拦截器
    axios.interceptors.request.use(
      function (config) {
        // 在发送请求之前做些什么
        // console.log('发送前 拦截器 ');
        document.querySelector('img').style.display = 'block'
        return config;
      },
      function (error) {
        // 对请求错误做些什么
        return Promise.reject(error);
      }
    );

    // 添加响应拦截器
    axios.interceptors.response.use(
      function (response) {
        document.querySelector('img').style.display = 'none'
        return response;
      },
      function (error) {
        // 超出 2xx 范围的状态码都会触发该函数。
        // 对响应错误做点什么
        return Promise.reject(error);
      }
    );
    const btn = document.querySelector('button')
    btn.addEventListener('click', function () {
      axios.get('http://www.itcbc.com:3006/api/getbooks').then(result => {
        console.log(result);
      })
    })

  </script>

十二、原生ajax

写法

    const xhr = new XMLHttpRequest()
    // 添加请求方式和请求链接a
    xhr.open('get','接口地址/api/getbooks?appkey=hwx123')
    // 发送请求
    xhr.send()
    // 添加 load 事件
    xhr.addEventListener('load',function () {
      // 返回的数据 xhr.response
      console.log(this.response);
      // 是JSON格式,转成对象
      const data = JSON.parse(this.response)
      console.log(data);
    })

1、get-携带参数

只能拼接再url上

const xhr = new XMLHttpRequest()
    xhr.open('get','接口地址/api/getbooks?appkey=hwx123&bookname=嘿嘿')
    xhr.send()
    xhr.addEventListener('load',function () {
      console.log(this.response);
    })

2、post-携带参数

string类型格式

	const xhr = new XMLHttpRequest()
    xhr.open('post', '接口地址/api/addbook')
    const data = 'bookname=Mkr&author=HWX&publisher=出版社&appkey=hwx123
    xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
    // 3、发送
    xhr.send(data)
    xhr.addEventListener('load', function () {
      console.log(this.response);
    })

对象类型格式

    const xhr = new XMLHttpRequest()
    xhr.open('post', '接口地址/api/addbook')
    const data = {
      bookname: 'MkrRR',
      author: 'HWXXXX',
      publisher: '出版社',
      appkey: 'hwx123',
    };
    // 1、转成JSON格式
    const str = JSON.stringify(data)
    // 2、指定请求头类型
    xhr.setRequestHeader('Content-type', 'application/json')
    // 3、发送
    xhr.send(str)
    xhr.addEventListener('load', function () {
      console.log(this.response);
    })

formdata类型格式

      const file = this.files[0] // 获取当前事件的文件,可以上传多个文件,数组
      console.log(file);
      const src = URL.createObjectURL(file) // 获取上传到浏览器内存中的文件
      img.src = src
      // http://www.itcbc.com:3006/api/formdata
      // 上传文件,给后端的参数 肯定是 formdata 类型
      const formdata = new FormData() // 创建一个空的formdata对象
      // 接口要求 参数名 avatar  参数类名file
      formdata.append('avatar', file) // 接口要求,把文件追加到formdata对象
      
      
      const xhr = new XMLHttpRequest()
      xhr.open('post','接口地址/api/formdata'),
      xhr.send(formdata)
      xhr.addEventListener('load',function () {
        console.log(this.response);
      })
    })

十三、请求报文&响应报文

客户端与服务器通信的过程是基于请求响应的。其中: 请求报文规定了客户端以什么格式把数据发送给服务器 响应报文规定了服务器以什么格式把数据响应给客户端

请求报文 - 格式

请求报文请求行(request line)、请求头部( header )、空行请求体 4 个部分组成

image.png

注意: 在浏览器中,GET 请求比较特殊,它只有请求头,没有请求体。 在浏览器中,POST、PUT、PATCH、DELETE 请求既有请求头,又有请求体

响应报文 - 格式

响应报文状态行响应头部空行响应体 4 个部分组成

image.png

URL参数

常用的5种请求方式都可以在URL后面携带请求参数。 由于URL的长度有限制,所以请求参数一般都比较小,比如不能做文件上传 常用的请求参数有两种写法 /api/xxx?参数=值&参数=值 (这种格式的字符串叫做查询字符串,所以这样的参数叫做查询参数)

// 直接写成查询字符串,并拼接到url后面
axios.get('/api/xxx?key=value&key=value')
// 按照axios的语法写,axios会帮我们转成查询字符串
axios.get('api/xxx', { params: { key: value, key: value } })

/api/xxx /值/值 (Restful 风格的接口用这种格式的参数)

// 只能自己拼接
axios.get('/api/xxx/100/zhangsan')

请求体

除GET请求以外,其他4种常用的请求方式,都可以设置请求体。 请求体的大小没有限制,所以可以提交大量的数据 常用的请求体格式有如下三种: 1、参数=值&参数=值 (查询字符串格式)

// axios.post的第二个参数,直接用查询字符串
axios.post('/api/xxx', 'key=value&key=value')

2、'{ "id": 1, "name": "zs" }' (JSON格式)

// axios.post的第二个参数,使用对象。axios会将它转成JSON格式
axios.post('/api/xxx', { id: 1, name: 'zs' })

3、new FormData() (FormData对象格式)

let fd = new FormData();
// axios.post的第二个参数,直接使用 FormData 对象
axios.post('/api/formdata', fd)

请求的时候,设置了不同格式的请求体,需要一个对应的请求头

1、参数=值&参数=值

Content-Type: application/x-www-form-urlencoded

2、'{ "id": 1, "name": "zs" }'

Content-Type: application/json

3、new FormData()

浏览器自动生成

http响应状态码

概念:http 响应状态码(Status Code)由三位数字组成,用来标识响应成功与否的状态。 作用:客户端浏览器根据响应状态码,即可判断出这次 http 请求是成功还是失败了。

image.png

响应状态码含义
200服务器成功返回请求数据
201新建或修改数据成功
202一个请求已经进入后台排队(异步任务)
204删除数据成功
304资源在客户端被缓存,响应体中不包含任何资源内容!
400发出信息有误
401用户没有权限(令牌、用户名、密码错误)
403用户得到授权,但是访问是被禁止的
404访问资源不存在
406请求格式不可得
410请求资源被永久删除,且不会被看到
500服务器发生错误
502网关错误
503服务不可用,服务器暂时过载或维护
504网关超时

http响应状态码 vs 业务状态码

1. 所处的位置不同:

在响应头的状态行中所包含的状态码,或者请求列表中的Status,叫做“响应状态码

image.png

在响应体的数据中所包含的状态码 (案例中叫做code) ,叫做“业务状态码image.png

2. 表示的结果不同:

响应状态码只能表示这次请求的成功与否(成功地失败了) 业务状态码用来表示这次业务处理的成功与否

3. 通用性不同:

响应状态码是由 http 协议规定的,具有通用性。每个不同的状态码都有其标准的含义,不能乱用。 业务状态码是后端程序员自定义的,不具有通用性。

十四、封装Ajax

1、什么是 XMLHttpRequest

是浏览器内置的一个构造函数

作用:基于 new 出来的 XMLHttpRequest 实例对象,可以发起 Ajax 的请求。 axios 中的 axios.get()、axios.post()、axios() 方法,都是基于 XMLHttpRequest(简称:XHR) 封装出来的!

2、主要实现步骤

主要的 4 个实现步骤: 创建 xhr 对象 调用 xhr.open() 函数 调用 xhr.send() 函数 监听 load 事件

image.png

let xhr = new XMLHttpRequest();
xhr.open('GET', 'http://xxx.com/api/xx');
xhr.send();
xhr.addEventListener('load', function () {
  console.log(this.response);
})

3、自己封装AJAX

function ajax({ url, type, data = '', success }) {
  const xhr = new XMLHttpRequest();

  type = type.toLowerCase() // 全部转成小写
  if (type === 'get') {
    (typeof data === 'object') && (data = new URLSearchParams(data).toString());
    xhr.open(type, url + '?' + data)
    xhr.send()
  } else if (type === 'post') {
    xhr.open(type, url)
    // 如果是字符串类型
    if (typeof data === 'string') {
      // 设置对应数据格式请求头
      xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
      xhr.send(data)
      // 如果是对象
    } else if (typeof data === 'object') {
      if (data instanceof FormData) { // 如果是formdata
        xhr.send(data)
      } else { // 普通对象
        xhr.setRequestHeader('Content-type', 'application/json')
        const str = JSON.stringify(data)
        xhr.send(str)
      }
    }

  }

  xhr.addEventListener('load', function () {
    const str = JSON.parse(this.response)
    success(str)
  })
}

十五、JSON数据

JSON(全称:JavaScript Object Notation)是一种数据交换格式,它本质上是用字符串的方式来表示对象或数组类型的数据。

1、JSON数据格式

JSON 数据的格式有两种:

① 对象格式

对象格式的 JSON 数据,最外层使用 { } 进行包裹,内部的数据为 "key": "value"键值对结构。其中: key 必须使用英文的双引号进行包裹 value 的值只能是字符串、数字、布尔值、null、数组、对象类型(可选类型只有这 6 种)

image.png

② 数组格式

数组格式的 JSON 数据,最外层使用 [ ] 进行包裹,内部的每一项数据之间使用英文的 , 分隔。其中: 每一项的值类型只能是字符串、数字、布尔值、null、数组、对象这 6 种类型之一。

image.png

2、JSON语法要求

  1. 使用 JSON 定义 JSON 格式的数据时,要遵守以下的 6 条规则:
  2. 属性名必须使用双引号包裹
  3. 字符串类型的值必须使用双引号包裹
  4. JSON 中不允许使用单引号表示字符串
  5. JSON 中不能写注释
  6. JSON 的最外层必须是对象数组格式(其他类型也可以,但多数是对象或数组格式)
  7. 不能使用 undefined函数作为 JSON 的值

3、JSON数据和JS数据相互转换

JSON转JS

JSON.parse(data)

JS转JSON

JSON.stringify(data)

\