深入浅出Ajax:现代Web开发中的异步交互艺术

441 阅读6分钟

前言

什么是Ajax

Ajax,全称Asynchronous JavaScript and XML,是一种网页开发技术,使得网页能够实现异步更新。这意味着,在不重新加载整个网页的情况下,Ajax可以使网页的一部分动态更新内容,从而提升用户体验和网页的交互性。

这一技术利用JavaScript、XML、HTML以及CSS等Web标准,向服务器发出背景中的HTTP请求,并处理响应,而用户无需离开当前页面或等待页面完全重载。尽管名字中含有XML,但现代的Ajax应用同样频繁使用JSON格式来交换数据,因为JSON更为轻量级且易于JavaScript处理。

Ajax的应用场景广泛,比如实时搜索建议、在线表单验证、动态加载更多内容(无限滚动)、实时数据推送等,都是Ajax技术的具体应用实例。自从2005年被Jesse James Garrett提出以来,Ajax已成为构建高性能、高互动性Web应用不可或缺的一部分。

实现Ajax的方法有几种?

有三种

XMLHttpRequest

image.png

Ajax的好处

Ajax不会引起整个页面的刷新

fdfc9f463e19a8c65dfe1c56f6203e0e.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>Document</title>
</head>
<body>
    <button id="btn">获取电影列表</button>
    <ul id="list"></ul>
    <script>
        let btn = document.getElementById('btn') //获取按钮
        btn.addEventListener('click', () => { //订阅一个点击事件
            console.log(123);
        })
    </script>
</body>
</html>

打印结果

image.png

分析

说明我们已经获取到了这个按钮,并且为它订阅了一个点击事件

那我们该怎么获取到电影数据?

我希望我点一下按钮浏览器就能向后端发一个http请求,所以我们需要一个接口的地址,https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList#!method=get,访问这个接口来获取我们想要的数据。

<script>
    let btn = document.getElementById('btn') //获取按钮
    btn.addEventListener('click', () => { //订阅一个点击事件
        // 朝一个接口发请求,获取到的数据展示在页面上
        let xhr = new XMLHttpRequest() // 创建一个Ajax实例
        xhr.open('GET', 'https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList#!method=get', true) // 配置发送的参数
        xhr.send()
})
</script>

实现效果

image.png

image.png

分析

首先通过let xhr = new XMLHttpRequest()创建一个Ajax实例,再通过调用open方法来配置发送的参数,

  • 第一个参数:表示 HTTP 请求的方法,常见的如 "GET"、"POST"、"PUT"、"DELETE" 等。
  • 第二个参数:表示请求的资源的 URL。
  • 第三个参数:一个布尔值,表示请求是否异步执行。如果是true(默认值),则表示请求是异步的,请求在后台进行,不会阻塞浏览器;false表示请求是同步的。

再调用send方法将请求发送出去。

注:open、send方法都是写在XMLHttpRequest()原型上的方法。

我们需要监听请求的过程

xhr.onreadystatechange = () => { // 监听请求的过程
        console.log(xhr.readyState);
    }
<script>
    let btn = document.getElementById('btn') //获取按钮
    btn.addEventListener('click', () => { //订阅一个点击事件
        // 朝一个接口发请求,获取到的数据展示在页面上
        let xhr = new XMLHttpRequest() // 创建一个Ajax实例
        xhr.open('GET', 'https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList#!method=get', true) // 配置发送的参数
        xhr.send() // 发送请求
        xhr.onreadystatechange = () => { // 监听请求的过程
            console.log(xhr.readyState);
        }
    })
</script>

打印结果

image.png

分析

XMLHttpRequest 的 readyState 属性有5个可能的值,分别代表不同的请求状态:

  • 0 -- xhr刚创建
  • 1 -- open执行
  • 2 -- 请求发送出去,响应头被接受
  • 3 -- 响应体正在解析
  • 4 -- 响应体解析完成

只有当readyState的值为4并且http的状态码为200时才表示已经拿到了后端返回的数据

<script>
    let btn = document.getElementById('btn') //获取按钮
    btn.addEventListener('click', () => { //订阅一个点击事件
        // 朝一个接口发请求,获取到的数据展示在页面上
        let xhr = new XMLHttpRequest() // 创建一个Ajax实例
        xhr.open('GET', 'https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList#!method=get', true) // 配置发送的参数
        xhr.send() // 发送请求
        xhr.onreadystatechange = () => { // 监听请求的过程
            if(xhr.readyState && xhr.status == 200) {
                console.log(xhr.responseText);
            }
        }
    })
</script>

打印结果

image.png

使用JSON.parse()把字符串转换为对象

console.log(JSON.parse(xhr.responseText));

打印结果

image.png

使用for循环将数据显示到页面,并且有几条数据就创建几个li

<script>
        let btn = document.getElementById('btn');    //获取按钮
        let ul = document.getElementById('list')

        btn.addEventListener('click', () => {
            // 朝一个接口发请求,获取到数据展示在页面上
            let xhr = new XMLHttpRequest(); // 创建一个ajax实例
            xhr.open('GET', 'https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList#!method=get', true); // 配置发送的参数
            xhr.send();
            xhr.onreadystatechange = () => {  //监听请求的过程
                if(xhr.readyState == 4 && xhr.status == 200) {
                    console.log(JSON.parse(xhr.responseText));
                    // 展示在页面上
                    const movieList = JSON.parse(xhr.responseText).movieList;
                    console.log(movieList);
                    for(let i = 0; i < movieList.length; i++) {
                        // movieList[i]
                        const li = document.createElement('li')
                        li.innerText = movieList[i].nm + '--' + movieList[i].star
                        ul.appendChild(li);
                    }
                }
            }
        })  // 订阅一个点击事件
    </script>

打印结果

image.png

分析 JSON.parse()已经将我们获取的数据转换成了数组,数组里面存放了12个对象,每个对象里面存放了我们需要的电影数据。所以我们需要循环遍历这个数组拿到里面的对象,再从对象中拿取数据li.innerText = movieList[i].nm + '--' + movieList[i].star赋给li,li.innerText 是一个属性,用于获取或设置HTML元素(在这里是<li>元素)内的文本内容。要想让ul中获取到li就需要获取到ullet ul = document.getElementById('list'),再使用ul.appendChild(li)将一个<li>元素添加到<ul>元素的最后一个子元素的位置上。于是我们就能实现在页面上以列表的形式显示电影数据。

Jquery方法

导入jquery库:

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>

<!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>Document</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
</head>
<body>
    <button id="btn">获取电影列表</button>
    <ul id="list"></ul>

    <script>
        let btn = document.getElementById('btn');    //获取按钮
        let ul = document.getElementById('list')

        btn.addEventListener('click', () => {
            $.ajax({
                url: 'https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList#!method=get',
                method: 'GET',
                success: function(res){
                    console.log(res);   
                }
            })
        })

    </script>
</body>
</html>

打印结果

image.png

分析 通过$.ajax()方法,朝地址url: 'https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList#!method=get'发请求,请求方法为GET method: 'GET',请求成功后通过success回调函数获取后端发给我的值。

向后端传数据,需要在$.ajax()里放入一个data{},在data{}里面放入你要传的数据

 $.ajax({
        url: 'https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList#!method=get',
        method: 'GET',
        data:{
            username: 'Lxp',
            age: 18
        },
        success: function(res){
            console.log(res);   
        }
 })

打印结果

image.png

分析 出现这个结果说明成功向后端传了数据

fetch

 <script>
    let btn = document.getElementById('btn');    //获取按钮
    let ul = document.getElementById('list')

    btn.addEventListener('click', () => {
        fetch("https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList?username='Lxp'&age=18")
        .then((res) => {
            // console.log(res); // 响应体
            return res.json()
        })
        .then((data) => {
            console.log(data);
        })
    })

</script>

打印结果

image.png

分析 调用了fetch()就会朝地址发请求,然后通过.then(res)获取到res响应体(then里面接收的是一个回调函数),此时的响应体还没被解析完全。

将响应体res格式化对象,return给下一个.then()

<script>
    let btn = document.getElementById('btn');    //获取按钮
    let ul = document.getElementById('list')

    btn.addEventListener('click', () => {
        fetch("https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList?username='Lxp'&age=18")
        .then((res) => {
            // console.log(res); // 响应体
            return res.json()
        })
        .then((data) => {
            console.log(data);
        })
    })

</script>

打印结果

image.png

就又拿到了这组数据,再通过for循环把数据显示到页面上。

如果这个接口需要我们传参数怎么办?

'https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList#!method=get'改为"https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList?username='Lxp'&age=18"将需要传的参数放在末尾。

image.png

什么是http状态码?

HTTP状态码(HTTP Status Code)是超文本传输协议(HTTP)响应消息中的一部分,它是一个三位数字代码,用于告知客户端(如浏览器)关于服务器对请求的处理结果。这些状态码帮助识别一个HTTP请求是否已成功被服务器处理,是否有错误,或者是否需要采取进一步的操作。

HTTP状态码分为五类,每种类别的第一个数字代表了响应的类型:

  1. 1xx(信息性状态码) :表示接收的请求正在处理,这类状态码是用来提供信息的,不需要客户端采取进一步操作。例如,100 Continue表明客户端应该继续其请求的剩余部分。
  2. 2xx(成功状态码) :表示请求已成功被服务器接收、理解,并接受了。最常见的如200 OK,表示请求已成功处理。
  3. 3xx(重定向状态码) :表示需要客户端采取进一步的操作才能完成请求。通常,这表示需要通过Location头字段指定的URI来完成重定向。例如,301 Moved Permanently表示请求的资源已被永久移动到新位置。
  4. 4xx(客户端错误状态码) :这类状态码表示客户端的请求有误,服务器无法处理。例如,404 Not Found表示服务器上找不到请求的资源。
  5. 5xx(服务器错误状态码) :表示服务器在处理请求的过程中发生了错误。例如,500 Internal Server Error表示服务器遇到了意料不到的情况,无法完成对请求的处理。

结语

三种方法你更喜欢用哪种就使用哪种。

qiuzan.jpg