第二节:Ajax核心技术 - XMLHttpRequest 对象

XMLHttpRequest 对象

XHR 1.0 是一个内建的浏览器对象,可以实现 Ajax 请求,Ajax技术的核心就是XMLHttpRequest 对象。

GET是在 open 里传参,POST是在 send 里传参。

原生 Js 实现基本的 GET 请求

获取所有数据
// 1.创建XMLHttpRequest 对象
var xhr = new XMLHttpRequest();

// 2.监听 onreadystatechange 事件
xhr.onreadystatechange = function () {
    // 2.1 当 Ajax 请求响应完后,再拿到服务器响应的数据
    if (xhr.readyState == 4) {
        // 2.2 用 JSON.parse 将结果转成对象
        console.log( JSON.parse(xhr.responseText) );
    }
}

// 3.设置请求方式和请求地址
xhr.open('get', 'http://www.liulongbin.top:3006/api/getbooks');

// 4.发送 ajax 请求
xhr.send();
获取指定数据
// 创建 xhr 对象
var xhr = new XMLHttpRequest();
// 注册事件
xhr.onreadystatechange = function () {
    // 当 Ajax 请求响应完后,再拿到服务器响应的数据
    if (xhr.readyState == 4) {
        // 用 JSON.parse 将结果转成对象
        console.log( JSON.parse(xhr.responseText) );
    }
}
// 设置请求头,并设置要获取的数据id
xhr.open('get', 'http://www.liulongbin.top:3006/api/getbooks?id=1');
// 提交请求体
xhr.send();
删除数据

删除 id 为 5686 的数据。

btns[2].addEventListener('click', (e = window.event) => {
    // 创建 xhr 对象
    var xhr = new XMLHttpRequest();

    // 注册事件
    xhr.onreadystatechange = function () {
        var res = xhr.responseText;
        if (xhr.readyState == 4) {
            // 用 JSON.parse 将结果转成对象
            console.log( JSON.parse(xhr.responseText) );
        }
    }

    xhr.open('get', 'http://www.liulongbin.top:3006/api/delbook?id=5686');

    // 提交请求体
    xhr.send();

});

原生 Js 实现基本的 POST 请求

和 GET请求有以下区别:

  • 在open 和 send 之间,必须设置请求头,通过 Content-Type 标识提交的数据类型(编码格式)。

    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    
  • 提交的请求体,不是拼接到url后面,而是当做send方法的参数。

    xhr.send('bookname=史记&author=司马迁&publisher=北京大学出版社');
    
添加数据
// 创建 xhr 对象
var xhr = new XMLHttpRequest();

// 注册事件
xhr.onreadystatechange = function () {
    if (xhr.readyState == 4) {
        // 用 JSON.parse 将结果转成对象
        console.log( JSON.parse(xhr.responseText) );
    }
}

xhr.open('post', 'http://www.liulongbin.top:3006/api/addbook');

// 设置请求头
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

// 提交请求体
xhr.send("bookname=书名&author=作者&publisher=出版社");

原生 Js 进行封装

还原 jQuery 中的 get 和 post 方法的封装。

分析:

  • 函数只有一个参数,是一个对象。
    • 包括:type、url、data、success 四个属性。
  • GET 和 POST 请求,都需要创建 xhr 对象,都需要设置 onreadystatechange 事件。
  • 当得到响应结果后,调用 success 函数后,把结果传递给 success 函数。
  • 需要把对象形式的请求参数,转换成查询字符串。
  • 由于GET和POST的 “open”和 “send”不一样,所以判断,然后分开写。
  • 优化(默认GET、大小写等等)。
// 调用
ajax({
    url: 'http://www.liulongbin.top:3006/api/getbooks',
    type: 'get',
    data: { id: 1 },
    success: function (res) {
        console.log(res);
    }
})

// 封装原生 Js 方法
function ajax(option) {

    // 1.将对象参数 转成 相应格式的字符串
    var params = objectToString(option.data);
    var type = option.type;

    var xhr = new XMLHttpRequest();

    xhr.onload = function () {
        if (xhr.status == 200) {
            console.log(JSON.parse(xhr.responseText));
        }
    }

    // 判断类型,返回
    if (type == 'get') {
        xhr.open(type, `${option.url}?${params}`);
        xhr.send();
    } else {
        xhr.open(type, option.url);
        xhr.send(params);
    }

}

// 请求参数
function objectToString(data) {
    var list = [];
    for (var key in data) {
        list.push(`${key}=${data[key]}`);
    }
	
    return list.join('&');
}

readyState 属性

Ajax 从创建 xhr 对象开始,一直到完全接收服务器返回的结果为止;我们可以把整个请求响应过程划分为5个阶段。并且可以使用 xhr.readyState 属性检测当前请求执行到哪个阶段了。

readyState 属性值为一个数字,不同的数字表示 Ajax 的不同状态。

属性值状态
xhr.readyState === 0初始状态,表示 xhr 对象一定创建了
xhr.readyState === 1表示 open 一定调用了
xhr.readyState === 2表示 send 一定调用了,并且已经接收到响应头
xhr.readyState === 3表示正在接收服务器返回的数据(可能已接收完毕,也可能正在接收中,取决于数据量的大小)
xhr.readyState === 4表示 Ajax 请求响应过程完成

20210414114934520

status 属性

status 属性表示 http 状态码,是一个数字,代码指示特定 HTTP 请求是否已成功完成。

相应分类:

  • 信息响应(100–199)
  • 成功响应(200–299)
  • 重定向(300–399)
  • 客户端错误(400–499)
  • 服务器错误 (500–599)

常用状态码:

  • 200 OK - 请求成功
  • 400 Bad Request - 1、语义有误,当前请求无法被服务器理解。2、请求参数有误。
  • 401 Unauthorized - 当前请求需要用户验证。
  • 404 Not Found - 请求失败,请求所希望得到的资源未被在服务器上发现。
  • 500 Internal Server Error - 服务器遇到了不知道如何处理的情况。

URL 编码解码

把中文和部分特殊符号转成 URL 的标准格式,这就是 url 编码。

作用:解决乱码问题。

编码

encodeURIComponent()

var name = '张三';

var r = encodeURIComponent(name);

console.log(r);		// "%E5%BC%A0%E4%B8%89"

解码

decodeURIComponent()

var r = "%E5%BC%A0%E4%B8%89";

console.log( decodeURIComponent(r) );	// 张三

XMLHttpRequest level 2

XHR 2.0 对XMLHttpRequest进行了扩展。

timeout 请求超时限制设置

timeout 和 ontimeout

// 1.设置请求超时时间,单位是毫秒
xhr.timeout = 30;

// 2.设置超时返回的内容
xhr.ontimeout = function () {
    console.log('请求超时了');
}
// 1.创建 xhr 对象
let xhr = new XMLHttpRequest();
// 2.设置请求方式
xhr.open('get', 'http://www.liulongbin.top:3006/api/getbooks');
// 3.发送请求
xhr.send();

// 4.设置请求超时时间,单位是毫秒
xhr.timeout = 1000;
// 5.设置超时返回的内容
xhr.ontimeout = function () {
    console.log('请求超时了');
}

// 6.监听
xhr.onreadystatechange = function () {
    if (xhr.readyState == 4 && xhr.status == 200) {
        console.log(xhr.responseText)
    }
}

onload 事件

onload 事件,其你去成功时触发,可以代替 onreadystatechange 事件。

使用 onload 代替 onreadystatechange,里面不用加判断,因为 onload 本身就是在请求成功时触发的。

xhr.onload = function() {
    // 成功响应后,获取响应结果
    console.log(JSON.parse(this.responseText));
}
// 1.创建 xhr 对象
let xhr = new XMLHttpRequest();
// 2.设置请求方式
xhr.open('get', 'http://www.liulongbin.top:3006/api/getbooks');
// 3.发送请求
xhr.send();

// 4.设置请求超时时间,单位是毫秒
xhr.timeout = 1000;
// 5.设置超时返回的内容
xhr.ontimeout = function () {
    console.log('请求超时了');
}

// 6.监听
xhr.onload = function() {
    // 成功响应后,获取响应结果
    if (xhr.status == 200) {
        console.log(JSON.parse(this.responseText));
    }
}

onerror 事件

在请求失败时触发。断网情况下触发。

xhr.onerror = function () {
    console.log('请求失败,请检查当前网络环境');
}
// 1.创建 xhr 对象
let xhr = new XMLHttpRequest();
// 2.设置请求方式
xhr.open('get', 'http://www.liulongbin.top:3006/api/getbooks');
// 3.发送请求
xhr.send();

// 4.监听
xhr.onload = function() {
    // 成功响应后,获取响应结果
    if (xhr.status == 200) {
        console.log(JSON.parse(xhr.responseText));
    }
}

// 5.请求失败
xhr.onerror = function () {
    console.log('请求失败,请检查当前网络环境');
}

onprogress 事件

在请求完成之前周期性调用的函数。readyState 为 3 时触发。

作用:可以使用 onprogress 事件,获取数据的接收(下载)进度。

xhr.onprogress = function (event) {
    // 已传输的数据量
    event.loaded;
    // 总共的数据量
    event.total;
}
// 1.创建 xhr 对象
let xhr = new XMLHttpRequest();
// 2.设置请求方式
xhr.open('get', 'http://www.liulongbin.top:3006/api/getbooks');
// 3.发送请求
xhr.send();

// 4.监听
xhr.onload = function() {
    // 成功响应后,获取响应结果
    if (xhr.status == 200) {
        console.log(JSON.parse(xhr.responseText));
    }
}

// 5.请求失败
xhr.onerror = function () {
    console.log('请求失败,请检查当前网络环境');
}

// 6.进度
xhr.onprogress = function (event) {
    // 已传输的数据量
    event.loaded;
    // 总共的数据量
    event.total;
}

onloadstart 事件

下载数据之前触发。

放在 open 和 send 之间。

xhr.onloadstart = function () {
    console.log('下载数据之前');
}

onloadend 事件

下载数据完成之后需触发。

放在 open 和 send 之间。

xhr.onloadend = function () {
    console.log('下载数据完成之后');
}
let xhr = new XMLHttpRequest();

xhr.open('get', 'http://www.liulongbin.top:3006/api/getbooks');

xhr.onloadstart = function () {
    console.log('下载数据之前');
}

xhr.onload = function () {
    if (xhr.status == 200) {
        console.log(JSON.parse(xhr.responseText));
    }
}

xhr.onloadend = function () {
    console.log('下载数据完成之后触发')
}

xhr.send();

FormData 对象

h5出现之后,新增的一个对象。用于管理表单数据。

创建 FormData 对象,可直接通过 xhr.send (FormData对象) 提交给服务器的接口。

// 获取元素
let form = document.querySelector('form');

// 实例化 formData 对象,传入form
let formData = new FormData(form);

xhr.open('post', '要提交的地址');

xhr.send(formData);

创建表单时,一定要设置 name 属性,传数据时要使用 name 属性当做 键名 来使用。

name 值是什么,键名就是什么。

20210419111628466

<html>
    <body>
        <form>
            <input type="text" name="username" id="username" >
            <input type="password" name="pwd" id="pwd" >
            <input type="button" id="btn" >
        </form>
    </body>
    
    <script>
        // 获取元素
        let form = document.querySelector('form');
        let btn = document.querySelector('#btn');
        
    	btn.addEventListener('click', function (event) {
            let xhr = new XMLHttpRequest();
            
            // 实例化 formData 对象,传入form
            let formData = new FormData(form);
            
            xhr.open('post', 'http://121.5.153.184:3000/formData');

            xhr.onload = function () {
                if (xhr.status == 200) {
                    console.log(JSON.parse(xhr.responseText));
                }
            }
            
            // 提交数据
            xhr.send(formData);
        });
    </script>
</html>

API 方法

append 方法

向对象中追加数据。
会追加一个自定义的属性。

formData.append('key', 'value');

20210419115013142

// 获取元素
let form = document.querySelector('form');
let btn = document.querySelector('#btn');

btn.addEventListener('click', function (event) {
    let xhr = new XMLHttpRequest();

    // 实例化 formData 对象,传入form
    let formData = new FormData(form);
    
    formData.append('age', 18);

    xhr.open('post', 'http://121.5.153.184:3000/formData');

    xhr.onload = function () {
        if (xhr.status == 200) {
            console.log(JSON.parse(xhr.responseText));
        }
    }

    // 提交数据
    xhr.send(formData);
});
set 方法

修改对象中的数据。

有同名属性,则修改该属性的值;没有同名属性,则新增该属性。

formData.set('key', 'value');

20210419115142833

// 获取元素
let form = document.querySelector('form');
let btn = document.querySelector('#btn');

btn.addEventListener('click', function (event) {

    // 实例化 formData 对象,传入form
    let formData = new FormData(form);
    
    formData.set('username', '李四');

    let xhr = new XMLHttpRequest();
    xhr.open('post', 'http://121.5.153.184:3000/formData');
    xhr.onload = function () {
        if (xhr.status == 200) {
            console.log(JSON.parse(xhr.responseText));
        }
    }
    // 提交数据
    xhr.send(formData);
});
delete 方法

从对象中删除数据。

删除指定的属性。

formData.delect('key');

20210419173652501

// 获取元素
let form = document.querySelector('form');
let btn = document.querySelector('#btn');

btn.addEventListener('click', function (event) {

    // 实例化 formData 对象,传入form
    let formData = new FormData(form);
    
    formData.delete('username');

    let xhr = new XMLHttpRequest();
    xhr.open('post', 'http://121.5.153.184:3000/formData');
    xhr.onload = function () {
        if (xhr.status == 200) {
            console.log(JSON.parse(xhr.responseText));
        }
    }
    // 提交数据
    xhr.send(formData);
});
get 方法

获取指定 key 的一项数据。

formData.get('key');

20210419174149422

// 获取元素
let form = document.querySelector('form');
let btn = document.querySelector('#btn');

btn.addEventListener('click', function (event) {

    // 实例化 formData 对象,传入form
    let formData = new FormData(form);
    
    console.log( formData.get('username') );

    let xhr = new XMLHttpRequest();
    xhr.open('post', 'http://121.5.153.184:3000/formData');
    xhr.onload = function () {
        if (xhr.status == 200) {
            console.log(JSON.parse(xhr.responseText));
        }
    }
    // 提交数据
    xhr.send(formData);
});
getAll 方法

获取指定 key 的全部数据,返回值是数组。

formData.getAll('key');

20210419174328879

forEach 方法

遍历对象中的数据。

formData.forEach(item => {
console.log(item);
})

20210419174515580

// 获取元素
let form = document.querySelector('form');
let btn = document.querySelector('#btn');

btn.addEventListener('click', function (event) {

    // 实例化 formData 对象,传入form
    let formData = new FormData(form);
    
    formData.forEach(item => {
        console.log(item);
    })

    let xhr = new XMLHttpRequest();
    xhr.open('post', 'http://121.5.153.184:3000/formData');
    xhr.onload = function () {
        if (xhr.status == 200) {
            console.log(JSON.parse(xhr.responseText));
        }
    }
    // 提交数据
    xhr.send(formData);
});

文件上传进度监听

待补充

CORS 跨域资源共享

待补充


JSON

本质是字符串,结构和对象差不多。

键名必须要加双引号,不能写 函数 、null 和 undefined。

{
    "name": "张三",
    "age": 18,
    "arr": [10, 20, 30, 40],
    "bl": true,
}

JSON字符串和JS数据转换

JS ----> JSON(序列化):JSON.stringify( JS数据 );

JSON ----> JS (反序列化):JSON.parse( JSON字符串 );

var data = {
    "name": "张三",
    "age": 18,
    "arr": [10, 20, 30, 40],
    "bl": true,
}

// js 数据序列化为字符串
var jsonStr = JSON.stringify(data);
// 结果:"{"name":"张三","age":18,"arr":[10,20,30,40],"bl":true}"

// 反序列化成对象
JSON.parse(jsonStr);
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孤安先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值