Ajax基础(笔记)

传统网站中存在的问题

  • 网速慢的情况下,页面加载时间长,用户只能等待
  • 表单提交后,如果一项内容不合格,需要重新填写所有表单内容
  • 页面跳转,重新加载页面,造成资源浪费,增加用户等待时间

1. 概述

它是浏览器提供的一套方法,可以实现页面无刷新更新数据,提高用户浏览网站应用的体验。

2. 应用场景

  1. 页面上拉加载更多数据
  2. 列表数据无刷新分页
  3. 表单项离开焦点数据验证
  4. 搜索框提示文字下拉列表

3. Ajax的运行环境

Ajax技术需要运行在网站环境中才能生效

4. Ajax运行原理

Ajax相当于浏览器发送请求与接收响应的代理人,以实现在不影响用户浏览页面的情况下,局部更新页面数据,从而提高用户体验

在这里插入图片描述

5. 创建Ajax对象

服务器端代码

const express = require('express');
const path = require('path');
const app = express();

app.use(express.static(path.join(__dirname, 'public')));
app.get('/first', (req, res) => {
    res.send('Hello Ajax');
})

app.listen(3000);
console.log('服务器启动成功');
  1. 创建Ajax对象
var xhr = new XMLHttpRequest();
  1. 告诉Ajax请求地址以及请求方式
xhr.open('get', 'http://www.example.com');
  1. 发送请求
xhr.send()
  1. 获取服务器给客户端的响应数据
xhr.onload = function() {
	console.log(xhr.responseText)
}

6. 服务器端响应的数据格式

在真实的项目中,服务器端大多数情况下会以JSON对象作为响应数据的格式,当客户端拿到响应数据是要将JSON数据和HTML字符串进行拼接,然后将拼接的结果展示在页面中。

在http请求与响应的过程中,无论是请求参数还是响应内容,如果是对象类型,最终都会被转换为对象字符串进行传输

JSON.parse() //将json字符串转换为json对象
<!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. 创建Ajax对象
        var xhr = new XMLHttpRequest();
        // 2. 告诉Ajax对象要想哪里发送请求,以什么方式发送请求
        //    1)请求方式  2)请求地址
        xhr.open("get", "http://localhost:3000/responseData");
        // 3. 发送请求
        xhr.send();
        // 4. 获取服务器端响应到客户端的数据
        xhr.onload = function() {
            //获取响应数据 xhr.responseText
            console.log(xhr.responseText);
            console.log(typeof xhr.responseText); //string

            //用JOSN.parse将其转化
            var responseText = JSON.parse(xhr.responseText);
            console.log(responseText);
            // 拼接
            var str = '<h2>' + responseText.name + '</h2>';
            document.body.innerHTML = str;
        }
    </script>

</body>

</html>

7. 请求参数传递

7.1 传统网站表单提交
  1. get参数在url中
  2. post在请求体中

提交表单时自动通过 name 属性匹配

7.2 Ajax中的请求
  1. GET请求方式
//请求参数要自己拼接
xhr.open('get', 'http://localhost:3000/get?username=handsome&age=12')

测试代码: 记得在路由里添加 /get 的响应

<!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>
    <p>
        <input type="text" id="username">
    </p>
    <p>
        <input type="text" id="age">
    </p>
    <p>
        <input type="button" value="提交" id="btn">
    </p>
    <script>
        var btn = document.getElementById('btn');
        btn.onclick = function() {
            var username = document.getElementById('username').value;
            var age = document.getElementById('age').value;

            var params = 'username=' + username + '&age=' + age;

            var xhr = new XMLHttpRequest();
            xhr.open('get', 'http://localhost:3000/get?' + params);
            xhr.send();
            xhr.onload = function() {
                console.log(xhr.responseText);
            }
        }
    </script>
</body>

</html>
  1. POST请求方式
//设置请求参数的类型,post请求必须要设置
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
//发送请求
xhr.send('name-zhangsan&age=20');

服务器端解析post请求参数的头信息

const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded());

代码示例:

const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const app = express();

app.use(express.static(path.join(__dirname, 'public')));

app.use(bodyParser.urlencoded());

app.get('/first', (req, res) => {
    res.send('Hello Ajax');
})

app.get('/responseData', (req, res) => {
    res.send({ "name": "zhanhsan" });
})

app.get('/get', (req, res) => {
    res.send(req.query);
})

app.post('/post', (req, res) => {
    res.send(req.body);
})

app.listen(3000);
console.log('服务器启动成功');
<!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>
    <p>
        <input type="text" id="username">
    </p>
    <p>
        <input type="text" id="age">
    </p>
    <p>
        <input type="button" value="提交" id="btn">
    </p>
    <script>
        var btn = document.getElementById('btn');
        btn.onclick = function() {
            var username = document.getElementById('username').value;
            var age = document.getElementById('age').value;

            var params = 'username=' + username + '&age=' + age;

            var xhr = new XMLHttpRequest();
            xhr.open('post', 'http://localhost:3000/post');

            // 设置响应头,固定写法(post请求必须要设置)
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

            // 参数在send中传递
            xhr.send(params);
            xhr.onload = function() {
                console.log(xhr.responseText);
            }
        }
    </script>
</body>

</html>
7.3 请求参数的格式
  1. application/x-www-form-urlencoded
name=zhangsan&age=20&sex=
  1. application/json
{name: 'zhangsan', age: '20', sex: ' 男'}

在请求头中指定Content-Type属性的值是application/json, 告诉服务器当前请求参数的格式是json。

JOSN.stringify() 
// 将json对象转化成为json字符串

注意:get请求时不能提交json对象的数据格式的,传统网站的表单提交也是不支持 json 对象数据格式的。

8. 获取服务器端的响应

8.1 Ajax 状态码

在创建Ajax对象,配置Ajax对象,发送请求,以及接受完服务器响应数据,之歌过程中的每一个步骤都会对应一个数值,这个数值就是Ajax状态码。

0:请求未初始化(还没有调用open())
1:请求已经建立,但是还没有发送(还没有调用send())
2:请求已经发送
3:请求正在处理中,通常响应中已经有部分数据可以用了
4:响应已经完成,可以获取并使用服务器的响应了

xhr.readyState // 获取Ajax状态码

onreadystatechage事件
当Ajax状态码发生变化时将自动触发该事件。

代码示例:

<!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 type="text/javascript">
        var xhr = new XMLHttpRequest();
        // 0: 请求未初始化( 还没有调用open())
        console.log(xhr.readyState);
        // 1: 请求已经建立, 但是还没有发送( 还没有调用send())
        xhr.open('get', 'http://localhost:3000/readystate')
        console.log(xhr.readyState);


        // 当ajax状态码发生变化的时候触发
        xhr.onreadystatechange = function() {
            // 2: 请求已经发送
            // 3: 请求正在处理中, 通常响应中已经有部分数据可以用了
            // 4: 响应已经完成, 可以获取并使用服务器的响应了

            console.log(xhr.readyState);
        }

        xhr.send();
    </script>
</body>

</html>
8.2 两种获取服务器端响应方式的区别
区别描述onload事件onreadystatechange事件
是否兼容IE低版本不兼容兼容
是否需要判断Ajax状态码不需要需要
被调用次数一次多次

9. Ajax错误处理

  1. 网络畅通,服务器端能够接收到请求,服务器端返回的结果不是预期结果。
    可以进行服务器端返回的状态码,分别进行处理,xhr.status 获取 http 状态码
  2. 网络畅通,服务器没有接受到请求,返回 404 状态码。
    检查请求地址是否错误。
  3. 网络畅通,服务器端能够接受到请求,服务器端返回 500 状态码。
    服务器端错误
  4. 当网络中断,请求无法发送到服务器端。
    会触发 xhr 对象下面的 onerror 事件,在 onerror 事件处理函数中对错误进行处理
<!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>发送ajax请求</button>
    <script>
        var btn = document.querySelector('button');
        btn.onclick = function() {
            var xhr = new XMLHttpRequest();
            xhr.open('get', 'http://localhost:3000/error')
            xhr.send();
            xhr.onload = function() {
                console.log(xhr.responseText);
                // console.log(xhr.starus);
                if (xhr.status == 400) {
                    alert('请求出错')
                }
            }
            xhr.onerror = function() {
                alert('网络中断,无法发送ajax请求')
            }
        }
    </script>
</body>

</html>

10. 低版本 IE 浏览器的缓存问题

在低版本的 IE 浏览器中,Ajax 请求有严重的缓存问题,即在请求地址不发生变化的情况下,只有第一次请求会真正发送到服务器端,后续的请求都会从浏览器的缓存中获取,即时服务器端的数据更新了,客户端依然拿到的是缓存中的旧数据。

解决方案:在请求地址后面加请求参数,保证每一次请求中的请求参数的值不相同。

xhr.open('get', 'http://www.example.com?t=' + Math.random());

11. 同步异步概述

https://blog.csdn.net/weixin_45773503/article/details/107877597

12 Ajax 封装

问题:发送一次请求代码过多,发送多次请求代码冗余且重复。
解决方案:将请求代码封装到函数中,发送请求时调用函数即可。

<!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>
        function ajax(options) {
            // 存储的是默认值
            var defaults = {
                type: 'get',
                url: '',
                data: {},
                header: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                success: function() {},
                error: function() {},
            };

            // 使用options对象中的属性覆盖defaults对象中的属性
            Object.assign(defaults, options);

            // 创建ajax对象
            var xhr = new XMLHttpRequest();
            // 拼接请求参数的变量
            var params = '';
            // 循环用户传递进来的对象格式参数
            for (var attr in defaults.data) {
                // 将参数转换为字符串形式
                params += attr + '=' + defaults.data[attr] + '&';
            }

            // 将参数最后面的&截取掉
            // 将截取的结果重新赋值给params变量
            params = params.substr(0, params.length - 1)

            // 判断请求方式
            if (defaults.type == 'get') {
                defaults.url = defaults.url + '?' + params;
            }
            // 配置ajax对象
            xhr.open(defaults.type, defaults.url);
            // 发送请求 如果是post请求
            if (defaults.type == 'post') {
                // 用户希望的向服务器端传递的请求参数的类型
                var contentType = defaults.header['Content-Type'];
                // 设置请求参数的类型
                xhr.setRequestHeader('Content-Type', contentType);
                // 如果类型为json
                if (contentType == 'application/json') {
                    // 向服务器端传递json数据格式的参数
                    xhr.send(JSON.stringify(defaults.data));
                } else {
                    // 向服务器端传递普通类型的请求参数
                    xhr.send(params);
                }
            } else {
                //如果是get请求
                xhr.send();
            }
            // 监听xhr下面的onload事件
            // 当xhr对象接收完响应数据后触发
            xhr.onload = function() {
                // 获取响应头中的数据
                var contentType = xhr.getResponseHeader('Content-Type');
                // 服务器端返回的数据
                var responseText = xhr.responseText;

                // 如果响应类型中包含application/json
                if (contentType.includes('application/json')) {
                    responseText = JSON.parse(responseText);
                }



                // 当http状态码等于200的时候
                if (xhr.status == 200) {
                    // 请求成功 调用处理成功情况的函数
                    defaults.success(responseText, xhr);
                } else {
                    // 请求失败 调用处理失败情况的函数
                    defaults.error(responseText, xhr);
                }

            }
        }
        ajax({
            // 请求方式默认 get
            // 默认格式: 'Content-Type': 'application/x-www-form-urlencoded',

            // 请求地址
            url: 'http://localhost:3000/responseData',
            data: {
                name: 'zhangsan',
                age: 20
            },
            success: function(data) {
                console.log('这里是success函数');
                console.log(data);
            },
            error: function(data, xhr) {
                console.log('这里是error函数' + data);
                console.log(xhr);
            }
        })


        // ajax({
        //     // 请求方式
        //     type: 'get',
        //     // 请求地址
        //     url: 'http://localhost:3000/responseData',
        //     /*
        //         1. 独立出来,兼容post和get
        //         2. 格式
        //             application/x-www-form-urlencoded
        //             application/json

        //         1. 传递对象数据类型对于函数的调用者更加友好
        //         2. 在函数内部对象数据类型转换为字符串数据类型更加方便
        //      */
        //     data: {
        //         name: 'zhangsan',
        //         age: 20
        //     },
        //     header: {
        //         // 'Content-Type': 'application/x-www-form-urlencoded',
        //         'Content-Type': 'application/json'
        //     },
        //     success: function(data) {
        //         console.log('这里是success函数');
        //         console.log(data);
        //     },
        //     error: function(data, xhr) {
        //         console.log('这里是error函数' + data);
        //         console.log(xhr);
        //     }
        // })
    </script>
</body>

</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值