掌握Ajax技术,拥抱动态Web交互新时代

366 阅读10分钟

一、Ajax是什么?

Ajax,全称为Asynchronous JavaScript and XML,即异步的JavaScript和XML,是一种在无需重新加载整个网页的情况下,能够更新部分网页内容的技术。Ajax允许网页与服务器进行异步数据交换,这意味着可以在后台与服务器交换数据,更新部分页面,而用户无需离开当前页面或等待页面完全重载。这大大提高了用户体验,使得网页感觉更快、更动态。

二、Ajax有什么用?

  1. 提高响应速度和交互性:通过异步数据加载,用户可以在不刷新整个页面的情况下查看新的内容或提交数据,减少了等待时间,使得网页感觉更加流畅和快速。
  2. 减少服务器负载:由于只需要加载部分内容而非整个页面,服务器传递的数据量减少,处理请求的负担也相应减轻,这对于高流量网站尤其重要。
  3. 实现页面局部更新:用户界面可以在不干扰用户操作的情况下动态更新,比如实时股价、天气预报更新,或者在线聊天室的即时消息显示。
  4. 增强应用功能:Ajax使得开发者能够在客户端实现更多复杂功能,如自动完成、动态表单验证、无刷新分页和筛选等,这些都极大地丰富了Web应用的功能性。
  5. 提升用户体验:减少页面刷新带来的视觉中断和等待时间,使得用户操作连贯,整体感受更加自然和舒适,有助于提高用户满意度和留存率。

三、如何实现Ajax?

html部分,先写一个按钮

<button id="btn">获取电影列表</button>
<ul id="list"></ul>

这段HTML代码定义了一个按钮(ID为"btn")和一个无序列表(ID为"list")。按钮用于触发获取电影列表的操作,无序列表用于展示获取到的电影信息。

分析

js部分要完成以下功能,以实现ajax:

当点击按钮时,使用Ajax对象以异步的形式向服务器发送一个请求

如果请求被允许(成功),则把获取的数据放入ul标签中,即返回数据,展示在页面上。

有三种方法实现以上功能,有优有劣。

1. 典型的原生JavaScript实现Ajax请求(麻烦)

let btn = document.getElementById('btn');
let ul = document.getElementById('list');

这两行JavaScript代码通过document.getElementById方法获取页面上的按钮和无序列表元素,并分别存储在变量btnul中,以便后续操作使用。

btn.addEventListener('click', () => {})

这一行代码为按钮添加了一个点击事件监听器。当按钮被点击时,会执行大括号内的匿名函数。

let xhr = new XMLHttpRequest();

这行代码创建了一个新的XMLHttpRequest对象,这是执行Ajax请求的关键对象,专门为实现ajax而设置的对象。

xhr.open('GET', 'https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList#!method=get', true);
xhr.send();

通过xhr.open方法配置了一个HTTP GET请求,指定了请求的URL和设置为异步请求(最后一个参数为true)。随后,xhr.send()方法发送了这个请求到服务器。

xhr.onreadystatechange = () => {
     if(xhr.readyState == 4 && xhr.status == 200) {
     }
}

这里为xhr对象设置了onreadystatechange事件处理器,当请求的状态改变时会执行。xhr.readyState == 4表示请求已完成,xhr.status == 200表示请求成功,两者条件都满足时进入if语句块。

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

这行代码读取了服务器响应的文本内容(xhr.responseText),使用JSON.parse将其转换为JavaScript对象,并打印到控制台以便调试。(检查自己是否成功获取到数据)

const movieList = JSON.parse(xhr.responseText).movieList;
for(let i = 0; i < movieList.length; i++){
    const li = document.createElement('li');
    li.innerText = movieList[i].nm + '--' + movieList[i].star;
    ul.appendChild(li);
}

这部分代码处理了成功的响应数据。首先,再次将响应内容解析为JSON对象,并从中提取出movieList数组。然后,使用for循环遍历这个数组,对每个电影项目创建一个新的<li>元素,将电影的名称(.nm)和主演(.star)信息设置为这个<li>元素的文本内容,最后将这个元素添加到页面上的无序列表(ul)中,实现动态展示电影列表的功能。

总结起来,这段代码实现了以下逻辑:

  1. 点击按钮触发Ajax请求。
  2. 向指定URL发送GET请求以获取电影列表数据。
  3. 监听请求状态,一旦请求成功完成,处理返回的JSON数据。
  4. 将处理后的电影数据动态添加到页面的无序列表中,呈现给用户。

整体代码

// 获取页面上的按钮和列表元素
let btn = document.getElementById('btn');
let ul = document.getElementById('list');

// 为按钮添加点击事件监听器
btn.addEventListener('click', function() {
    // 创建一个XMLHttpRequest对象,这是进行Ajax通信的核心组件
    let xhr = new XMLHttpRequest();

    // 配置请求: 使用GET方法,请求的目标URL以及设置请求为异步模式
    xhr.open('GET', 'https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList#!method=get', true);

    // 发送请求到服务器
    xhr.send();

    // 设置一个事件处理器来监听请求的状态变化
    xhr.onreadystatechange = function() {
        // 当请求完成(状态4)且响应状态为200(成功)时,执行以下代码
        if(xhr.readyState === 4 && xhr.status === 200) {
            // 解析从服务器返回的JSON格式数据
            let movieData = JSON.parse(xhr.responseText);
            // 从解析的数据中提取电影列表
            const movieList = movieData.movieList;

            // 清空列表以准备展示新数据(如果需要的话)
            ul.innerHTML = '';

            // 遍历电影列表
            for(let i = 0; i < movieList.length; i++) {
                // 为每部电影创建一个新的列表项(li元素)
                let listItem = document.createElement('li');
                // 设置列表项的内容为电影名和主演
                listItem.textContent = movieList[i].nm + '--' + movieList[i].star;
                // 将列表项添加到无序列表中
                ul.appendChild(listItem);
            }
        }
    };
});

补充: 有些人可能对if(xhr.readyState === 4 && xhr.status === 200)不了解,为什么这样就判定成功了,这里做一下补充:

  • xhr.readyState === 4: 这个条件检查请求的状态是否为4,readyState属性表示请求/响应过程的不同阶段。它共有5个可能的值:

    • 0: 请求未初始化
    • 1: 服务器连接已建立
    • 2: 请求已接收
    • 3: 请求处理中(通常响应中已有部分数据可访问,但尚未完成)
    • 4: 请求已完成且响应已就绪

    readyState变为4,意味着整个请求已经完成,响应数据已经可以使用。

  • xhr.status === 200: 这个条件检查HTTP响应状态码是否为200。HTTP状态码是用来表示网页服务器超文本传输协议响应状态的3位数字代码。200状态码表示请求已成功处理,一切正常。常见的其他状态码还包括404(未找到)、500(服务器内部错误)等。

结合在一起,if(xhr.readyState === 4 && xhr.status === 200)就是在确认请求已经结束并且服务器返回了一个成功的响应。只有在这两个条件都满足时,才会执行紧跟其后的代码块,通常是在这里处理响应数据,比如解析JSON、更新DOM等。这是确保我们只在获得有效响应时才进行后续操作,避免处理不完整或错误的响应数据

2.使用jQuery库来实现Ajax请求(不是最优)

核心代码 Javascript

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

使用jQuery的$.ajax方法发送一个Ajax请求:

  • url: 指定请求的URL,这里是模拟接口,用于获取电影列表。
  • method: 请求的方法,这里是GET。
  • data: 请求携带的数据,尽管在这个GET请求中传递这些数据可能不会以查询字符串形式附加到URL上(取决于服务器配置和jQuery的具体行为),通常GET请求的查询参数会直接拼接在URL上,但这里作为示例展示了如何传递额外数据。
  • success: 请求成功后的回调函数,res参数是服务器返回的数据。在这个示例中,只是简单地将响应数据打印到控制台。

jQuery$.ajax方法已经帮你实现了核心逻辑,你只需要在相应位置上填上相应的数据就可以。

整体代码

// 获取按钮和列表元素
let btn = document.getElementById('btn');
let ul = document.getElementById('list');

// 为按钮添加点击事件监听器
btn.addEventListener('click', function() {
    // 使用jQuery的$.ajax方法发起一个GET类型的Ajax请求
    $.ajax({
        // 设置请求的URL
        url: 'https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList#!method=get',
        // 请求的方法为GET
        method: 'GET',
        // 请求携带的数据,尽管在GET请求中这些数据通常不会以这种方式发送(通常应为查询参数)
        data: {
            username: '笑笑', // 示例用户名
            age: 18          // 示例年龄
        },
        // 请求成功后的回调函数
        success: function(res) {
            // 打印服务器响应的数据到控制台
            console.log(res);
            // 下面是示例代码,用于将获取到的电影列表数据渲染到页面上
            // 假设res是包含电影列表的对象,其中movieList是电影数组
            /* 
            const movieList = res.movieList;
            movieList.forEach(movie => {
                let li = document.createElement('li');
                li.textContent = `${movie.name} - ${movie.director}`;
                ul.appendChild(li);
            });
            */
        }
    });
});

对于那些已经在使用jQuery库的项目,因为它提供了简洁、链式操作的API,使得Ajax请求的编写变得简单直观。然而,随着时间的推移和Web技术的发展,一些新的趋势和替代方案逐渐受到青睐,这主要是出于以下几个原因:

  • 体积与性能:jQuery是一个大型库,包含了许多功能,而不仅仅是Ajax。对于只需Ajax功能的现代项目,引入整个jQuery可能会导致页面加载时间增加和资源占用过多。相比之下,使用原生的XMLHttpRequest或者更现代的fetchAPI可以实现更轻量级的解决方案。
  • 现代浏览器的支持:随着现代浏览器对ES6及更高版本特性的全面支持,原生的JavaScript功能已经足够强大,可以直接使用fetchAPI来处理Ajax请求,它提供了更符合现代JavaScript编程习惯的Promise API,使得异步编程更加简洁和易于管理。
  • 模块化和框架的发展:随着前端工程化的推进,像React、Vue、Angular这样的现代前端框架成为主流,它们通常推荐使用自己的数据管理方式(如React的Hooks、Vue的axios等)或者提倡使用更小、更专注于单一职责的库来处理网络请求,以适应模块化和组件化的开发模式。
  • 社区和趋势:随着前端技术栈的快速迭代,开发者社区对新技术的探索和采纳,新的工具和实践不断涌现,像Axios这样的独立库因其灵活性和易用性受到了广泛的欢迎,它们提供了丰富的特性集,比如拦截请求、自动转换请求和响应数据等,而不需要引入整个jQuery库。

综上所述,虽然使用jQuery的$.ajax依然是可行的选项,特别是在维护旧项目或者团队对此有深厚积累的情况下,但从长远看,考虑到性能优化、代码的现代性和生态的多样性,更多的项目倾向于采用原生API或现代库来处理Ajax请求。这就是我们接下来要说的第三种实现Ajax的方法

3. 使用Fetch API来实现Ajax请求(经常用且最优)

核心代码

btn.addEventListener('click', () => {
    fetch("https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList#!method=get?username='曾总'&age=18")  // ? username = '曾总'&age=18
    .then((res) => {
        return res.json()
    })
    .then((data) => {
        console.log(data);
    })
})

首先,通过getElementById方法获取页面中ID为"btn"的按钮元素和ID为"list"的无序列表元素。

btn.addEventListener('click', () => {
    // ...
});

为按钮添加一个点击事件监听器,当按钮被点击时,执行里面的箭头函数。


fetch("https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList#!method=get?username='曾总'&age=18")

使用Fetch API发送一个GET请求到指定的URL。这里直接在URL后面添加查询参数(username='曾总'&age=18),这是传递请求参数的一种方式,但需要注意,由于URL中特殊字符需要编码,实际上正确的传递方式应该是对参数进行URL编码,例如username=%E6%9B%BE%E6%80%BB&age=18。不过,对于演示目的,这里的写法能直观理解参数传递的概念。

.then((res) => {
    return res.json();
})

fetch返回一个Promise,当请求成功时,第一个.then被调用。这里接收到了响应对象res,然后调用res.json()将响应体转换为JSON格式的Promise。这个转换是必要的,因为原始响应体可能不是JSON格式,而是Blob、FormData等。

.then((data) => {
    console.log(data);
})

上一步转换成JSON之后的Promise链继续用.then处理,这里接收到了转换后的JSON数据,并将其打印到控制台。

注意:为了完整实现需求,可能还需要进一步处理data,比如遍历电影列表并将其添加到页面上,这部分逻辑可以根据实际需求添加到第二个.then的处理函数中。

四、结语

在现代Web开发领域,Ajax技术无疑扮演着至关重要的角色,它不仅极大地丰富了用户体验,还推动了Web应用向着更高效、更互动的方向发展。通过上述探讨,我们不仅回顾了Ajax的基本概念及其带来的显著优势,还深入学习了三种实现Ajax请求的方法:原生JavaScript、jQuery的$.ajax方法,以及现代Web开发中越来越受欢迎的Fetch API。

  • 原生JavaScript提供了最基础、最灵活的实现方式,适合于任何JavaScript环境,但代码相对繁琐。
  • jQuery的$.ajax简化了Ajax操作,凭借其链式调用和广泛的支持,成为过去很长一段时间内的首选,尽管在现代轻量化和性能优先的趋势下,它的使用有所减少。
  • Fetch API作为现代Web标准的一部分,以其原生支持、基于Promise的异步处理机制和更简洁的语法,成为了目前实现Ajax请求的优选方案,特别适合追求代码质量与性能的现代项目。

选择合适的Ajax实现方式,依据项目需求、团队熟悉度及技术栈的兼容性来决定。无论是维护遗留系统、快速构建原型,还是开发高性能、现代化的Web应用,深刻理解Ajax的核心原理与不同实现手段,都将使你能够更加灵活地应对各种交互需求,从而在Web开发领域游刃有余。拥抱Ajax,开启你的动态Web交互之旅,让用户的每一次点击都充满惊喜与流畅。