JS第二十四次笔记

31 阅读4分钟

1 AJAX原理——XMLHttpRequest

1.1 定义

image.png

1.2 使用步骤

image.png

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

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <script>
    // 目标:使用XHLHttpRequest对象与服务器通信
    // 1.创建XMLHttpRequest对象(可传参也可不传)
    const xhr = new XMLHttpRequest();
    // 2.配置请求方法和URL地址
    xhr.open('GET', 'http://hmajax.itheima.net/api/province');
    // 3.监听loadend事件,接收响应结果
    xhr.addEventListener('loadend', () => {
      // json数据是字符串,需要转换为对象
      console.log(JSON.parse(xhr.response));
      // 保存json中的list数据
      const data = JSON.parse(xhr.response).list;
      // 将list中的内容渲染到页面中
      document.body.innerHTML = data.map(item => item).join('<br>')
    })
    // 4.发送请求
    xhr.send();
  </script>
</body>

</html>

结果:

image.png

1.2 XMLHttpRequest——查询参数

image.png

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

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <script>
    // 目标:使用XHR携带查询参数,展示某个省下属的城市列表
    // 1.创建对象 XHR
    const pname = '河北省';
    const xhr = new XMLHttpRequest();
    // 2.配置请求方法和URL地址
    xhr.open('GET', `http://hmajax.itheima.net/api/city?pname=${pname}`);
    // 3.监听loadend事件,接收响应结果
    xhr.addEventListener('loadend', () => {

      console.log(xhr.response);
      // 因为得到的是json数据,所以需要转换为对象
      const result = JSON.parse(xhr.response);
      console.log(result);
    })
    // 4.发送请求
    xhr.send();
  </script>
</body>

</html>

结果:

image.png

1.2.1 案例——地区查询

将对象格式数据,转化为查询字符串 键=值&键=值

const parmasObj=new URLSearchParams({
    pname,
    cname
})
//`toString()` 的作用是将 `URLSearchParams` 对象转换为一个查询字符串,以便将其附加到 URL 的末尾。这是为了构造一个完整的 URL,用于发起 HTTP 请求。
const str=paramsObj.toString()

image.png

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

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>案例_地区查询</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css">
  <style>
    :root {
      font-size: 15px;
    }

    body {
      padding-top: 15px;
    }
  </style>
</head>

<body>
  <div class="container">
    <form id="editForm" class="row">
      <!-- 输入省份名字 -->
      <div class="mb-3 col">
        <label class="form-label">省份名字</label>
        <input type="text" value="北京" name="province" class="form-control province" placeholder="请输入省份名称" />
      </div>
      <!-- 输入城市名字 -->
      <div class="mb-3 col">
        <label class="form-label">城市名字</label>
        <input type="text" value="北京市" name="city" class="form-control city" placeholder="请输入城市名称" />
      </div>
    </form>
    <button type="button" class="btn btn-primary sel-btn">查询</button>
    <br><br>
    <p>地区列表: </p>
    <ul class="list-group">
      <!-- 示例地区 -->
      <!-- <li class="list-group-item">东城区</li> -->
    </ul>
  </div>
  <!-- <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> -->
  <script>
    // const obj = {
    //   pname: '广东省',
    //   cname: '广州市'
    // }
    // /**
    //  * 目标: 根据省份和城市名字, 查询对应的地区列表
    // */
    // //  1. 创建实例对象
    // const xhr = new XMLHttpRequest();

    // // 2. 调用open方法
    // xhr.open('GET', `http://hmajax.itheima.net/api/area?pname=${obj.pname}&cname=${obj.cname}`);
    // // 3. 监听loadend事件
    // xhr.addEventListener('loadend', () => {
    //   const result = JSON.parse(xhr.response);
    //   console.log(result);
    // })
    // // 4. 发送请求
    // xhr.send();


    // 更简易的写法
    // 目标:点击按钮,查询对应的地区列表
    // 1.点击事件注册
    document.querySelector('.sel-btn').addEventListener('click', () => {
      // 2. 获取省份和城市名字
      const pname = document.querySelector('[name="province"]').value;
      const cname = document.querySelector('[name="city"]').value;
      console.log(pname, cname);

      // 传一个对象,会返回一个实例对象
      // 得到目标格式需要使用tostring方法
      const parmasObj = new URLSearchParams({
        pname,
        cname
      });
      console.log(parmasObj.toString());
      // 3. 发送请求
      const xhr = new XMLHttpRequest();

      xhr.open('GET', `http://hmajax.itheima.net/api/area?${parmasObj.toString()}`);
      xhr.addEventListener('loadend', () => {
        const result = JSON.parse(xhr.response);
        document.querySelector('.list-group').innerHTML = JSON.parse(xhr.response).map(item => {
          return `<li class="list-group-item">${item}</li>`
        }).join('')
      })
      // 4. 发送请求
      xhr.send();
    })
    // 5.渲染页面



  </script>
</body>

</html>

1.3 XMLHttpRequest——数据提交

image.png

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

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <button class="reg-btn">注册用户</button>
</body>

<script>
  document.querySelector('.reg-btn').addEventListener('click', () => {
    const xhr = new XMLHttpRequest();
    xhr.open('POST', 'http://hmajax.itheima.net/api/register')
    xhr.addEventListener('loadend', () => {
      console.log(xhr.response);
    })
    // 设置请求头
    //1.设置请求头数据类型 (根据接口文档设置)
    xhr.setRequestHeader('Content-Type', 'application/json')
    //2.在send方法中携带参数
    const obj = {
      username: 'csqsdc',
      password: '1234554646',
    }
    // 将obj对象转换为json字符串
    const data = JSON.stringify(obj)
    xhr.send(data)//请求体参数携带在send方法中
  })
</script>
</html>

结果: image.png

2 Promise

2.1 语法

image.png

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

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>认识Promise</title>
</head>

<body>
  <script>
    /**
     * 目标:使用Promise管理异步任务
    */
    //  1.创建Promise对象
    const p = new Promise(function (resolve, reject) {
      // 2.执行异步任务
      //如果成功,则调用resolve方法
      resolve('成功')//相当于调用then的回调函数
      //如果失败,则调用reject方法
      reject('失败')//相当于调用catch的回调函数

      // 3.接收成功或者失败的结果
      p.then(function (res) { console.log(res) })//实参,它的形参是resolve
        .catch(function (err) { console.log(err) })//实参,它的形参是reject
    })
  </script>
</body>

</html>

image.png

2.2 promise的三种状态

Promise存在状态凝固特性,一旦状态从(pending)修改为fulfilled或者是rejected后就不会再次修改了 image.png

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

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <script>
    // 1.创建Promise对象
    const p = new Promise((resolve, reject) => {
      // 2.执行异步任务
      setTimeout(() => {
        // 3.根据条件执行resolve或reject
        resolve(new Errorr('模拟AJAX请求——失败结果'))

      }, 2000)
    })
    console.log(p)
    //(1). 待定(pending)状态:创建了Promise对象,但还没有调用resolve或reject
    //(2). 成功(fulfilled)状态:调用resolve方法
    //(3). 失败(rejected)状态:调用reject方法
    // 2.执行异步任务
    p.then(result => {
      console.log(result)
    }).catch(err => {
      console.log(err)
    })
  </script>
</body>

</html>

3.案例——使用promise和XHR获取省份列表

image.png

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

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>案例_使用Promise+XHR_获取省份列表</title>
</head>

<body>
  <p class="my-p"></p>
  <script>
    /**
     * 目标:使用Promise管理XHR请求省份列表
     * 
     *  1. 创建Promise对象
     * 
     *  2. 执行XHR异步代码,获取省份列表
     *  3. 关联成功或失败函数,做后续处理
    */
    // 1. 创建Promise对象
    const p = new Promise(function (resolve, reject) {
      // 2.执行XHR异步代码,获取省份列表
      const xhr = new XMLHttpRequest();
      xhr.open('GET', 'https://hmajax.itheima.net/api/province')
      xhr.addEventListener('loaded', () => {
        if (xhr.status == 200) {

        }
      })
      // 发送请求
      xhr.send();
    })
    // 使用promise在函数外面获取结果
    p.then(res => {
      const p = document.querySelector('.my-p')
      p.innerHTML = JSON.parse(res).list.map(item => item).join('<br>')
      console.log(JSON.parse(res).list)
    })

  </script>
</body>

</html>

结果:

image.png

3 封装简易版 axios

image.png

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

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>

  <script>
    <!-- 1. 定义myAxios函数,接收配置对象,返回Promise对象 -->
    function myAxios(option) {
      // 解构配置对象
      const { url, method } = option
      // 两个参数,一个成功,一个失败
      // 回调函数
      return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.open(method, url)
        xhr.addEventListener('loaded', () => {
          // console.log(xhr.response)
          resolve(xhr.response)

        })
        xhr.send()
      })
    }
    //  2. 调用myAxios函数,传入配置对象
    myAxios({
      url: 'https://hmajax.itheima.net/api/province',
      method: 'GET',
    }).then(res=>{
      console.log(res)
    })
  </script>
</body>

</html>

3.1 封装简易axios函数,获取地区列表

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

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>

  <script>
    // <!-- 1. 定义myAxios函数,接收配置对象,返回Promise对象 -->
    function myAxios(option) {
      // 解构配置对象
      let { url, method, parmas } = option
      // console.log(parmas)
      // 判断parmas是否存在(使用tostring将对象转化为字符串)
      parmas = parmas ? new URLSearchParams(parmas).toString : ''
      // 拼接URl地址
      parmas ? url + '?' + parmas : url
      // 两个参数,一个成功,一个失败
      // 回调函数
      return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.open(method, url)
        xhr.addEventListener('loaded', () => {
          // console.log(xhr.response)
          resolve(JSON.parse(xhr.response))

        })
        xhr.send()
      })
    }
    myAxios({
      url: 'http://hmajax.itheima.net/api/area',
      method: 'GET',
      parmas: {
        pname: '河北省',
        cname: '邯郸市'
      }
      // then方法打印出响应数据
    }).then(res => {
      document.querySelector('.my-p').innerHTML = res.list.map(item => item).join('<br>')
    })
  </script>
</body>

</html>

3.2 封装_简易axios_注册用户

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

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <button>click me</button>
  <script>
    // const btn = document.querySelector('button')
    // <!-- 1. 定义myAxios函数,接收配置对象,返回Promise对象 -->
    function myAxios(option) {
      // 解构配置对象
      let { url, method, params, data } = option

      // 判断params是否存在
      params = params ? new URLSearchParams(params).toString() : ''
      // 拼接URL地址
      url = params ? url + '?' + params : url

      return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.open(method, url)

        // 设置请求头
        if (data) {
          xhr.setRequestHeader('Content-Type', 'application/json')
          // 处理数据
          data = JSON.stringify(data)
        }

        xhr.addEventListener('load', () => {
          resolve(JSON.parse(xhr.response))
        })

        xhr.send(data)
      })
    }

    document.querySelector('button').addEventListener('click', () => {
      myAxios({
        url: 'http://ajax-api.itheima.net/register',
        method: 'POST',
        data: {
          username: 'csqqqq',
          password: '123456'
        }
      }).then(res => {
        console.log(res)
      }).catch(error => {
        console.error('请求失败:', error)
      })
    })
  </script>
</body>

</html>

结果

image.png