AJAX学习(2)

目录

一.XMLHttpRequest

二.XMLHttpRequest------查询参数

三.案例------地区查询

四.XMLHttpRequest_数据提交

五.Promise

六.Promise三种状态

七.Promiseee+XHR获取省份列表(案例)

八.封装-简易axios-获取省份列表

九.封装-简易axios-获取地区列表

十.封装-简易axios-注册用户


一.XMLHttpRequest

1.XMLHttpRequest定义:

XMLHttpRequest(XHR)对象用于与服务器交互。通过 XMLHttpRequest 可以在不刷新页面的情况下请求特定 URL,获取数据。这允许网页在不影响用户操作的情况下,更新页面的局部内容。XMLHttpRequest 在AJAX 编程中被大量使用。

2.关系:axios内部采用XMLHttpRequest与服务器交互

3.使用

  • 创建XMLHttpRequest对象
XML 复制代码
const xhr = new XMLRequest()
xhr.open('请求方法','请求URL网址')
xhr.addEventListener('loadend', ()=>{
    console.log(xhr.response)
})
xhr.send()
  • 配置请求方法和请求URL地址
  • 监听loadend事件,接受响应结果
  • 发起请求

4.案例:

XML 复制代码
<!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>XMLHttpRequest_基础使用</title>
</head>

<body>
  <p class="my-p8"></p>
<script>
  /**
   * 目标:使用XMLHttpRequest对象与服务器通信
   *  1. 创建 XMLHttpRequest 对象
   *  2. 配置请求方法和请求 url 地址
   *  3. 监听 loadend 事件,接收响应结果
   *  4. 发起请求
   */
  const xhr = new XMLHttpRequest()
  xhr.open('GET', 'https://hmajax.itheima.net/api/province')
  xhr.addEventListener('loadend', ()=> {
    console.log(xhr.response)
    //转换为了对象
    const  data = JSON.parse(xhr.response)
    console.log(data.list.join('<br>'))
    document.querySelector('.my-p8').innerHTML = data.list.join('<br>')
  })
  xhr.send()

</script>
</body>

</html>

二.XMLHttpRequest------查询参数

1.定义:浏览器提供给服务i的额外信息,让服务器返回浏览器想要的数据

2.语法:http://xxxx.com/xxxx/xxxx?参数名1 = 值1 & 参数名2 = 值2

3.案例:

XML 复制代码
<!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>XMLHttpRequest_查询参数</title>
</head>

<body>
<p class="hello"></p>
<script>
  /**
   * 目标:使用XHR携带查询参数,展示某个省下属的城市列表
   */
  const xhr = new XMLHttpRequest();
  xhr.open('GET', 'https://hmajax.itheima.net/api/city?pname=辽宁省');
  xhr.addEventListener('loadend', () => {
    console.log(xhr.response);
    const data = JSON.parse(xhr.response);
    console.log(data.list.join('<br>'));
    document.querySelector('.hello').innerHTML = data.list.join('<br>')
  })
  xhr.send();
</script>
</body>

</html>

三.案例------地区查询

XML 复制代码
<!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>
  /**
   * 目标: 根据省份和城市名字, 查询对应的地区列表
   */
  //1.查询按钮绑定点击事件
  document.querySelector('.sel-btn').addEventListener('click', ()=>{
    //2.获取输入框的值
    const pname = document.querySelector('.province').value
    const cname = document.querySelector('.city').value

    //3.组织查询参数到字符串
    const qOBJ = {
      pname,
      cname
    }
    const paramsOBJ = new URLSearchParams(qOBJ)
    const queryString = paramsOBJ.toString()
    console.log(queryString)

    //4.清空现有列表
    document.querySelector('.list-group').innerHTML = '<li class="list-group-item">加载中...</li>'

    //5.使用fetch查询地区列表
    fetch(`https://hmajax.itheima.net/api/area?${queryString}`)
      .then(response => {
        if (!response.ok) {
          throw new Error('网络响应不正常')
        }
        return response.json()
      })
      .then(data => {
        console.log(data)
        // 使用反引号创建模板字符串
        const htmlStr = data.list.map(areaName => {
          return `<li class="list-group-item">${areaName}</li>`
        }).join('')
        console.log(htmlStr)
        document.querySelector('.list-group').innerHTML = htmlStr
      })
      .catch(error => {
        console.error('查询失败:', error)
        document.querySelector('.list-group').innerHTML = `<li class="list-group-item text-danger">查询失败: ${error.message}</li>`
      })
  })
</script>
</body>
</html>

四.XMLHttpRequest_数据提交

1.需求:通过XHR提交用户名和密码,完成注册功能

请求头设置Content-Type:application/json

请求体携带JSON字符串

XML 复制代码
const xhr = new XMLHttpRequest()
xhr.open('请求方法','请求URL网址')
xhr.addEventListener('loadend',()=>{
    console.log(xhr.response)
})
//告诉服务器,我传递的内容类型,是JSON字符串
xhr.setRequestHeader('Content-Type','application/json')
//准备数据并转成JSON字符串
const user = {username:'用户名', password:'密码'}
const userStr = JSON.stringify(user)
//发送请求体
xhr.send(userStr)

2.案例:

XML 复制代码
<!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>XMLHttpRequest_数据提交</title>
</head>

<body>
<button class="reg-btn">注册用户</button>
<script>
  /**
   * 目标:使用xhr进行数据提交-完成注册功能
   */
  document.querySelector('.reg-btn').addEventListener('click', () => {
    const xhr = new XMLHttpRequest()
    xhr.open('POST','https://hmajax.itheima.net/api/register')
    xhr.addEventListener('loadend',()=>{
      console.log(xhr.response)
    })
//告诉服务器,我传递的内容类型,是JSON字符串
    xhr.setRequestHeader('Content-Type','application/json')
//准备数据并转成JSON字符串
    const user = {username:'huopengzhao', password:'123456'}
    const userStr = JSON.stringify(user)
//发送请求体
    xhr.send(userStr)

  })
</script>
</body>

</html>

五.Promise

1.定义:Promise对象用于表示一个异步操作的最终完成(或失败)及其结果值

2.好处:

  • 逻辑更清晰
  • 了解axios函数内部的运行机制
  • 能够解决回调函数低于问题
XML 复制代码
//1.创建promise对象
const p = new Promise((resolve, reject) =>{
    //2.执行异步任务-并传递结果
    //成功调用:resolve(值)触发then()执行
    //失败调用:reject(值)触发catch()执行

})
//3.接受结果
p.then(result =>{
    //成功
}).catch(error=》{
    //失败
})

案例:

XML 复制代码
<!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管理异步任务
   */
  const p = new Promise((resolve, reject) => {
    //执行异步代码
    setTimeout(() => {
      //成功调用resolve(.then接受),失败调用reject(.catch接受)
      //resolve('模拟AJAX请求成功')
      reject(new Error('模拟AJAX请求失败'))
    },2000)
  })
  //3.获取结果
  p.then((result) => {
    console.log(result)
  }).catch((error) => {
    console.log(error)
  })
</script>
</body>

</html>

六.Promise三种状态

1.作用:了解Promise对象如何关联的处理函数,以及代码执行顺序

2.概念:一个promise对象必将处于以下几种状态

(Promise对象一旦被兑现/拒绝就是已敲定,状态无法再被改变)

  • 待定(pending):初始状态,既没有兑现,也没有拒绝
  • 已兑现(fulfilled):意味着操作成功完成
  • 已拒绝(rejected):意味着操作失败

3.案例

java 复制代码
 /**
   * 目标:认识Promise状态
   */
    // 1. 创建Promise对象(pending-待定状态)
  const p = new Promise((resolve, reject) => {

    console.log('Promise对象开始执行')
    // 2. 执行异步代码
      setTimeout(() => {
        // resolve('模拟AJAX请求-成功结果')
        //resolve()=>'fulfilled状态-已兑现'=>then()
        //reject()=>'rejected状态-已拒绝'=>catch()
        reject(new Error('模拟AJAX请求-失败结果'))
      }, 2000)
    })
  console.log(p)

  // 3. 获取结果
  p.then(result => {
    console.log(result)
  }).catch(error => {
    console.log(error)
  })

七.Promiseee+XHR获取省份列表(案例)

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>案例_使用Promise+XHR_获取省份列表</title>
</head>
<body>
<p class="hello"></p>

<script>
  const p = new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest()
    xhr.open('GET', 'https://hmajax.itheima.net/api/province')
    xhr.addEventListener('load', () => {
      if (xhr.status >= 200 && xhr.status < 300) {
        try {
          const response = JSON.parse(xhr.response)
          resolve(response)
        } catch (e) {
          reject(new Error('解析JSON失败'))
        }
      } else {
        reject(new Error(`请求失败: ${xhr.status}`))
      }
    })
    xhr.addEventListener('error', () => {
      reject(new Error('网络请求失败'))
    })
    xhr.send()
  })

  p.then(result => {
    console.log(result)
    if (result.list && Array.isArray(result.list)) {
      document.querySelector('.hello').innerHTML = result.list.join('<br>')
    } else {
      throw new Error('返回数据格式不正确')
    }
  }).catch(error => {
    console.error(error)
    document.querySelector('.hello').innerHTML = `加载失败: ${error.message}`
  })
</script>
</body>
</html>

八.封装-简易axios-获取省份列表

需求:基于Promise+XHR封装myAxios函数,获取省份列表

步骤:

  1. 定义myAxios函数,接收配置对象,返回Promise对象
  2. 发起XHR请求,默认请求方法为GET
  3. 调用成功/失败的处理程序
  4. 使用myAxios函数,获取省份列表展示
java 复制代码
function myAxios(config){
    return new Promise((resolve,reject) =>{
    //xhr请求
    //调用成功/失败的处理程序
})
}
myAxios({
    url:'目标资源地址'
}).then(result => {

}).catch(error => {

})

代码实现:

html 复制代码
<!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>封装_简易axios函数_获取省份列表</title>
</head>

<body>
<p class="hello"></p>
<script>
  /**
   * 目标:封装_简易axios函数_获取省份列表
   *  1. 定义myAxios函数,接收配置对象,返回Promise对象
   *  2. 发起XHR请求,默认请求方法为GET
   *  3. 调用成功/失败的处理程序
   *  4. 使用myAxios函数,获取省份列表展示
   */
  function myAxios(config){
    return new Promise((resolve,reject) =>{
      //xhr请求
      //调用成功/失败的处理程序
      const xhr = new XMLHttpRequest()
      xhr.open(config.method || 'GET', config.url)
      xhr.addEventListener('loadend', () => {
        if(xhr.status >= 200 && xhr.status < 300){
          resolve(JSON.parse(xhr.responseText))
        }else {
          reject(new Error(xhr.response))
        }
      })
      xhr.send()
    })
  }
  myAxios({
    url:'https://hmajax.itheima.net/api/province'
  }).then(result => {
    console.log(result)
    document.querySelector('.hello').innerHTML = result.list.join('<br>')
  }).catch(error => {
    console.log(error)
    document.querySelector('.hello').innerHTML = error.message
  })
</script>
</body>

</html>

九.封装-简易axios-获取地区列表

需求:修改myAxios函数支持传递查询参数,获取'辽宁省','大连市'对应地区列表展示

要求

  1. myAxios函数调用后,传入params选项
  2. 基于URLSearchParams转换查询字符串
  3. 使用自己封装的myAxios函数展示地区列表
javascript 复制代码
function myAxios(config){
    return new Promise((resolve, reject) => {
    //XHR请求 - 判断params选项,携带查询参数
    //调用成功/失败的处理程序
})
}

myAxios({
    url:'目标自已按地址',
    params:{
        参数名1:值1,
        参数名2:值2
    }
})

代码展示:

html 复制代码
<!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>封装_简易axios函数_获取地区列表</title>
</head>

<body>
<p class="my-p"></p>
<script>
  /**
   * 目标:封装_简易axios函数_获取地区列表
   *  1. 判断有params选项,携带查询参数
   *  2. 使用URLSearchParams转换,并携带到url上
   *  3. 使用myAxios函数,获取地区列表
   */
  function myAxios(config) {
    return new Promise((resolve, reject) => {
      const xhr = new XMLHttpRequest()
      //1.判断params选项,是否携带查询参数
      if(config.params){
        //2.使用URLSearchParams转换,并携带到url上
        const paramsObj = new URLSearchParams(config.params)
        const queryString = paramsObj.toString()
        //把查询参数字符串,拼接在url?后面
        config.url += `?${queryString}`
      }
      xhr.open(config.method || 'GET', config.url)
      xhr.addEventListener('loadend', () => {
        if (xhr.status >= 200 && xhr.status < 300) {
          resolve(JSON.parse(xhr.response))
        } else {
          reject(new Error(xhr.response))
        }
      })
      xhr.send()
    })
  }
//3.使用myAxios函数,获取地区列表
  myAxios({
    url:'https://hmajax.itheima.net/api/area',
    params:{
      pname: '辽宁省',
      cname: '大连市'
    }
  }).then(result =>{
    console.log(result)
    document.querySelector('.my-p').innerHTML = result.list.join('<br>')
  }).catch(error =>{
    console.log(error)
    document.querySelector('.my-p').innerHTML = error.message
  })

</script>
</body>

</html>

十.封装-简易axios-注册用户

需求:修改myAxios函数支持传递请求体数据,完成注册用户功能

步骤:

  1. myAxios函数调用后,判断data选项
  2. 转换数据类型,在send方法中发送
  3. 使用自己封装的myAxios函数完成注册用户功能
javascript 复制代码
function myAxios(config){
    return new Promise((resolve, reject) => {
    //XHR请求 - 判断data选项,携带查询参数
    //调用成功/失败的处理程序
})
}

myAxios({
    url:'目标自已按地址',
    data:{
        参数名1:值1,
        参数名2:值2
    }
})

代码实现:

html 复制代码
<!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>封装_简易axios函数_注册用户</title>
</head>

<body>
<button class="reg-btn">注册用户</button>
<script>
  /**
   * 目标:封装_简易axios函数_注册用户
   *  1. 判断有data选项,携带请求体
   *  2. 转换数据类型,在send中发送
   *  3. 使用myAxios函数,完成注册用户
   */
  function myAxios(config) {
    return new Promise((resolve, reject) => {
      const xhr = new XMLHttpRequest()

      if (config.params) {
        const paramsObj = new URLSearchParams(config.params)
        const queryString = paramsObj.toString()
        config.url += `?${queryString}`
      }
      xhr.open(config.method || 'GET', config.url)

      xhr.addEventListener('loadend', () => {
        if (xhr.status >= 200 && xhr.status < 300) {
          resolve(JSON.parse(xhr.response))
        } else {
          reject(new Error(xhr.response))
        }
      })
      //1.判断data选项,是否携带请求体
      if (config.data) {
        const jsonStr = JSON.stringify(config.data)
        xhr.setRequestHeader('Content-Type', 'application/json')
        xhr.send(jsonStr)
      }else{
        //如果没有请求体数据,就正常发起请求
        xhr.send()
      }

    })
  }
  document.querySelector('.reg-btn').addEventListener('click', () => {
    //3.使用myAxios函数,完成注册用户
    myAxios({
      url:'https://hmajax.itheima.net/api/register',
      method:'POST',
      data:{
        username:'huopengzhao',
        password:'123456'
      }
    }).then(result => {
      console.log(result)
    }).catch(error => {
      console.log(error)
    })

  })
</script>
</body>

</html>