前端基础学习——数据请求之ajax详解

77 篇文章 7 订阅

Ajax

1. URL网址的基本概念

  • URL概念:统一资源定位符 (Uniform Resource Locator)
    • 俗称网址,用来标识某个资源在网络中的唯一位置。
  • 组成部分:

2. 请求和响应的流程

  • 任意的一次网络访问(访问网站根目录、img加载、audio加载、link标签…)都是下面的3个步骤
  • 步骤
    • 1 请求:客户端请求服务器
    • 2 处理:服务器的内部处理(找找资源等…)
    • 3 响应:服务器响应客户端

2.1. 浏览器的network面板的使用

network用来检测浏览器发出的每次请求以及响应内容

  • 打开方式:浏览器 -> F12 -> Network -> 进行操作
    • 左侧为所有请求的请求列表
    • 顶部具有请求的筛选功能
    • 选择某一条请求后,可以查看请求的具体内容
      • request 请求
      • response 响应

3. 网站中的资源

  • 常见资源为:图片、文字、音视频、css文件…
  • 核心资源:数据(根据数据生成页面结构可以让页面制作变简便,维护成本降低)
  • 与html、css、js的关系
    • html是网页的结构、骨架
    • css是网页的样式、颜值
    • js是网页的行为、控制交互
    • 数据是网页灵魂

4. 资源的请求方式get post

  • 请求类型:get() post()
  • 语义的区别
    • get 用来进行获取资源的请求操作
      • 获取图片、音视频、js文件、css文件、地址栏输入地址回车,location.href,a标签跳转。。。
    • post 用来进行发送资源的请求操作
      • 表单提交form标签(get、post均可,可以自己选择)
      • ajax也可以发送get和post请求
  • 可发送数据大小有区别
    • get请求受限制于浏览器对url的限制,2M左右
    • post请求理论上无大小限制,实际上受限制于服务端实际的业务需求和处理能力
  • 可发送的数据格式有区别
    • get请求只能发送文本格式数据
    • post请求不限制发送的数据格式,服务器会根据业务需求进行处理

4.1. 传统请求发送方式

  • 地址栏
  • a标签
  • location.href
  • img.src link.href 我们无法进行干预
  • form+submit

上面发送请求的方式,统一特点:都会出现跳转(有的是我们无法干预的)

实际页面功能制作时,很多的功能虽然请求了新的数据,但是并没有出现跳转,只是局部刷新

结论:传统的请求方式无法满足现代网页的所有功能,就需要使用新的请求方式----AJAX。

5. AJAX简介

Ajax(Asynchronous Javascript And XML(异步 JavaScript 和 XML))

  • 作用:用来发送请求的一种方式
  • 实现方式:浏览器提供了一个XMLHttpRequest的构造函数,创建的对象用来进行ajax操作
  • 特点:无需刷新页面,也可以进行请求响应处理(局部刷新)

5.1. 同步和异步的概念

同步任务:

  • 执行顺序:代码按顺序从上往下一个一个执行。
  • 除了异步任务都是同步任务。

异步任务:

  • 为什么要有异步任务: 因为某些任务较为耗时,或执行时间不确定,为了避免卡住(阻塞)后续代码,设置为异步任务。
  • 常见异步任务有:
    • 定时器
      • 示例:无论定时器的时间为多少,都会比同步任务执行晚。
    • Ajax
  • 执行顺序:异步任务的执行一定晚于同步任务

5.2.js语言特性和单线程

js的语言特性

  • js是弱类型语言
  • js是动态语言
  • js是脚本语言
  • js是基于对象的语言(面向对象语言)
  • js是基于原型的语言
  • js是事件驱动的语言
  • js是单线程的语言

单线程(只有一个人干活)

  • 因为js中具有DOM操作,例如修改元素颜色,单个线程操作不会与其他线程产生干扰冲突
  • es5后js也出现了多线程的概念,但是有限制,多个线程只能进行辅助操作,主线程进行控制

多线程(有好多人干活)

6. jQuery中的ajax操作

6.1. $.get()的使用

没有请求参数,不接收响应数据

$.get(地址); // 通过浏览器调试工具的network查看请求的细节和响应的数据

$.get('http://www.liulongbin.top:3006/api/getbooks');

没有请求参数,接收响应数据

$.get(地址, function(res) {
    // 响应接收完毕后,执行回调函数
    // res代表响应的数据,如果res为JSON格式,jQuery会自动转换为js对象
});

$.get('http://www.liulongbin.top:3006/api/getbooks', function (res) {
    // 响应完成后,触发这个回调函数
    // 回调函数的参数表示响应的数据,一般称为response或res
    console.log(res);
});

有请求参数,接收响应数据

请求参数:请求中发送给服务端的数据,是一个对象

$.get(地址, 请求参数组成的对象, 回调函数);

$.get('http://www.liulongbin.top:3006/api/getbooks', { id: 2 }, function (res) {
    console.log(res);
});

6.2. $.post()的使用

没有请求参数,不接收响应数据

$.post(地址); // 通过浏览器调试工具的network查看请求的细节和响应的数据

$.post('http://192.168.141.45:3005/common/post');

没有请求参数,接收响应数据

$.post(地址, function(res) {
    // 响应接收完毕后,执行回调函数
    // res代表响应的数据,如果res为JSON格式,jQuery会自动转换为js对象
});

$.post('http://192.168.141.45:3005/common/post', function (res) {
    console.log(res);
})

有请求参数,接收响应数据

请求参数:请求中发送给服务端的数据,是一个对象

$.post(地址, 请求参数组成的对象, 回调函数);

$.post(
    'http://192.168.141.45:3005/common/post',
    { name: 'jack', age: 18 },
    function (res) {
        console.log(res);
    });

6.3. $.ajax()的使用

  • type表示请求方式,默认为’GET’,可以设置为’GET’/‘POST’
  • url表示请求地址,只有url属性是必须设置的
  • data表示请求参数,对象结构
  • success表示响应成功时的处理函数,res参数,表示响应内容

1.使用$.ajax()发送GET请求

$.ajax({
    // type: 'GET', // 默认为GET,一般发送GET请求时,都不设置type
    url: 'http://192.168.141.45:3005/common/get',
    data: {
        name: 'jack',
        age: 18,
        gender: '男'
    },
    success: function (res) {
        console.log(res);
    }
}); 
  1. 使用$.ajax()发送POST请求
$.ajax({
    type: 'POST',
    url: 'http://192.168.141.45:3005/common/post',
    data: {
        width: 200,
        height: 600,
        bgc: 'red'
    },
    success: function (res) {
        console.log(res);
    }
});

$.get()$.post()$.ajax()的关系

$.ajax()是jQuery中设置的一个用来进行ajax请求发送的方法 ,$.get()$.post()只是调用了$.ajax()实现的功能

7. 接口的概念

  • 接口:
    • 概念:指的是能够提供某种能力的事物。
  • 应用程序编程接口(API)
    • 概念:提供应用程序编程能力的事物
    • WebAPI
      • 浏览器提供的,与web开发相关的一些API,本质上就是一堆属性方法
    • 内置对象API
      • js解析器提供的,用于js基础语法操作的一些API,本质上就是一堆属性方法
    • js的组成部分和浏览器的主要构成
      • 浏览器的两个主要构成部分
        • 内核(渲染引擎): html和css渲染,WebAPI
        • js解析器:执行ECMAScript
      • 规范相关内容:
        • w3c规范:html css webAPI
        • ECMA规范:语法(含内置对象)
  • 数据接口:
    • 概念:是能够提供数据的一种事物。表现形式就是一个URL
      • 简单来说,能够提供数据的一个URL地址,就称为是数据接口
    • 说明:当进行前端和后端(服务器)交互时,所说的’接口’,指的就是数据接口。
    • 使用方式:严格遵守接口的文档进行操作即可。

8. 时间戳格式化方法

// 用来将时间戳进行日期格式化的函数:
function dateFormat(timestamp) {
    var time = new Date(parseInt(timestamp));
    var y = time.getFullYear();
    var m = time.getMonth() + 1;
    m = m > 9 ? m : '0' + m;
    var d = time.getDate();
    d = d > 9 ? d : '0' + d;
    var h = time.getHours();
    h = h > 9 ? h : '0' + h;
    var mm = time.getMinutes();
    mm = mm > 9 ? mm : '0' + mm;
    var s = time.getSeconds();
    s = s > 9 ? s : '0' + s;
    return y + '-' + m + '-' + d + ' ' + h + ':' + mm + ':' + s;
}

var time=1575808501208;    // -------时间戳
time=dateFormat(time);

9. 表单form

表单在网页中主要负责数据采集功能。HTML中的标签,就是用于采集用户输入的信息 ,

由于标签的submit提交操作会发生跳转,用户体验很差,页面之前的状态和数据会丢失。

经常使用表单进行数据采集(用输入框等元素获取输入内容),使用ajax进行请求发送即可(提交)

9.1. 表单的组成部分

  • form标签

  • 表单域:input标签。。textarea。。select…

  • 提交按钮:

    <input type="submit">  
    <button type="submit">提交</button>
    
    • 如果希望button不进行提交操作,只是普通按钮,可以设置type为button

9.2. form标签的属性

标签的属性则是用来规定如何把采集到的数据发送到服务器。
  • action
    • action 属性的值是一个URL地址,定义向何处提交表单,默认值为当前页面的 URL 地址。
    • 注意:当提交表单后,页面会立即跳转到 action 属性指定的 URL 地址。
  • target
    • 规定在何处打开 action URL。
    • _self 默认在本窗口打开 _blank在新窗口打开
  • method
    • 规定以何种方式把表单数据提交到 action URL ,get和post
  • enctype
    • 规定在发送表单数据之前如何对数据进行编码
    • 在涉及到文件上传的操作时,必须将 enctype 的值设置为 multipart/form-data

9.3. 表单操作的特点

  • 提交数据时会出现页面跳转的情况
  • 提交后,页面之前的状态和数据会丢失。

9.4. 常用请求方式

  • 使用表单进行数据采集(用输入框等元素获取输入内容),使用ajax进行请求发送即可(提交)

10. 表单和ajax结合使用

10.1. 监听表单提交事件

在 jQuery 中,可以使用如下两种方式,监听到表单的提交事件:

$('#form1').submit(function(e) {
   alert('监听到了表单的提交事件')
})

$('#form1').on('submit', function(e) {
   alert('监听到了表单的提交事件')
})

10.2. 阻止表单的默认提交行为

在submit事件中,设置e.preventDefault()方法即可(推荐), return false也可以

$('#form1').submit(function(e) {
   // 阻止表单的提交和页面的跳转
   e.preventDefault()
})

$('#form1').on('submit', function(e) {
   // 阻止表单的提交和页面的跳转
   e.preventDefault()
})

10.3. serialize()快速获取表单中的数据

jQuery的serialize()方法可以快速获取表单中的所有数据(只能获取纯文本数据)

为了简化表单中数据的获取操作,jQuery 提供了 serialize() 函数,其语法格式如下 :

$(selector).serialize()

serialize() 函数的好处:可以一次性获取到表单中的所有的数据。

<form id="form1">
    <input type="text" name="username" />
    <input type="password" name="password" />
    <button type="submit">提交</button>
</form>

$('#form1').serialize()
// 调用的结果:
// username=用户名的值&password=密码的值
注意:在使用 serialize() 函数快速获取表单数据时,必须为每个表单元素添加 name 属性!
  • 注意:这种内容格式可以通过$.get $.post $.ajax进行直接发送
  • 注意表单元素如果没有name,数据是无法正确提交的

11. XMLHttpRequest

XMLHttpRequest(简称 xhr)是浏览器提供的 Javascript 对象,通过它,可以请求服务器上的数据资源。

jQuery 中的 Ajax 函数,就是基于 xhr 对象封装出来的.

12. get请求

12.1. get请求基本使用

步骤:

  1. 创建xhr对象
  2. 调用xhr.open():设置请求方式和请求地址
  3. 调用xhr.send(): 发送请求(这一步是异步操作)
  4. 设置onreadystatechange事件,监听请求的各种状态
    • readyState是xhr的属性,用来表示请求发送的状态
      • 取值为4代表下载完毕
      • 必须确保readyState为4才能使用响应的数据
    • xhr.status 代表请求是否成功
      • 200代表请求是成功的
    • xhr.responseText 代表接收的响应内容
// 1 创建xhr对象
var xhr = new XMLHttpRequest();
// 2 调用xhr.open():设置请求方式和请求地址
xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks');
// 3 调用xhr.send(): 发送请求,这一步是异步操作
xhr.send();
// 4 设置事件,监听请求的各种状态
// readyState是xhr的属性,用来表示请求发送的状态
//    取值为4代表下载完毕
//    必须确保readyState为4才能使用响应的数据
// 进一步检测:
//      xhr.status 代表请求是否成功
//      200代表请求是成功的
xhr.onreadystatechange = function () {
    // 4.1 检测xhr.readyState取值和xhr.status取值
    if (xhr.readyState === 4 && xhr.status === 200) {
        // 4.2 接收响应的数据即可
        // 原生接收的响应内容是JSON格式,需要自己进行转换
        // jQuery会自动转换
        console.log(xhr.responseText);
    }
};

12.2. 带有参数的get请求

  • 位置:在xhr.open()的参数2 url后面书写参数内容

  • 名称:参数的形式称为查询字符串

  • 格式: ?名=值&名=值…

    • 其中 名=值&名=值… 称为url编码格式,英文为urlencoded
  • jQuery的get请求和原生get请求的本质是一样

// 1 创建xhr对象
var xhr = new XMLHttpRequest();
// 2 调用open:设置请求方式和请求地址
// 如果希望设置get请求的请求参数,需要放置在open()参数2地址的最后位置
// 书写方式为:  地址?名=值&名=值....
// 名称说明: 名=值&名=值称为url编码格式  urlencoded
xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks?id=3&name=jack&age=18');
// 3 调用send: 发送请求,这一步是异步操作
xhr.send();
// 4 设置事件,监听请求的各种状态
xhr.onreadystatechange = function () {
    // 4.1 检测xhr.readyState取值和xhr.status取值
    if (xhr.readyState === 4 && xhr.status === 200) {
        // 4.2 接收响应的数据即可
        console.log(xhr.responseText);
    }
};

13. xhr对象的readyState属性

XMLHttpRequest 对象的 readyState 属性,用来表示当前 Ajax 请求所处的状态。

每个 Ajax 请求必然处于以下状态中的一个:

值                状态                            描述
0               unsent                  XMLHttpRequest对象已被创建,但尚未调用open()方法
1               opened                  open()方法已经被调用
2               headers_received        send()方法已经被调用,响应头也已经被接收
3               loading                 数据接收中
4                done                   Ajax请求完成,下载完毕

14. url编码

URL 地址中,只允许出现英文相关的字母、标点符号、数字,因此,在 URL 地址中不允许出现中文字符。

如果 URL 中需要包含中文这样的字符,则必须对中文字符进行编码(转义)。

URL编码的原则:使用安全的字符(没有特殊用途或者特殊意义的可打印字符)去表示那些不安全的字符。

URL编码原则的通俗理解:使用英文字符去表示非英文字符。

  • url编码是url对地址的一种处理方式(将中文部分进行编码转换)
  • 浏览器会进行自动的url处理,无需我们自己操作
  • 两个用来处理的函数
    • encodeURI() 编码
    • decodeURI() 解码
// 使用encodeURI() 对内容进行编码
console.log(encodeURI('黑马程序员'));
console.log(encodeURI('传智播客'));

// 使用decodeURI() 对内容进行解码
console.log(decodeURI('%E9%BB%91%E9%A9%AC%E7%A8%8B'));
console.log(decodeURI('%E5%BA%8F%E5%91%98'));

15. post请求的发送方式

步骤:

  1. 创建xhr对象
  2. 调用xhr.open()
  3. 设置Content-Type(内容格式、内容类型)
    • xhr.setRequestHeader(‘Content-Type’, ‘application/x-www-form-urlencoded’)
  4. 调用xhr.send(数据)
    • 数据为url编码格式
  5. 设置readystatechange事件获取响应内容
// 1 创建xhr对象
var xhr = new XMLHttpRequest();

// 2 调用xhr.open()
xhr.open('POST', 'http://www.liulongbin.top:3006/api/addbook');

// 3 设置Content-Type内容格式(固定写法)
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

// 4 调用xhr.send()
//    - 如果具有请求参数,书写在send中,格式也是url编码格式(名=值&名=值...)
xhr.send('bookname=老人与海&author=海明威&publisher=大海图书出版社');

// 5 设置readystatechange事件,接收响应的数据
xhr.onreadystatechange = function () {
    if (xhr.readyState === 4 && xhr.status === 200) {
        console.log(xhr.responseText);
    }
};

16. get与post发送方式的区别

请求参数的书写位置不同:

  • get请求方式:在xhr.open()的url后面使用?连接
  • post请求:在xhr.send()中书写

post请求需要设置Content-Type

17. 封装ajax函数

封装用来将对象转换为url编码的函数

// 封装函数,用于将对象转换为url编码格式
function urlencoded(obj) {
    var arr = []; // 声明数组用来保存结果
    // 遍历obj,获取所有属性
    for (var k in obj) {
        // k - 属性名 - 字符串类型
        // obj[k] - 属性值
        arr.push(k + '=' + obj[k]);
    }
    return arr.join('&');
}

封装ajax函数

  • 转换字符串为大小写的字符串方法
    • 字符串.toUpperCase() 转换为大写字母
    • 字符串.toLowerCase() 转换为小写字母
// 封装用来发送ajax请求的函数
//  参数:
//    对象
//      - type 请求方式
//      - url 请求地址
//      - data 请求参数
//      - success 回调函数
function ajax(options) {
    // 1 创建xhr对象
    var xhr = new XMLHttpRequest();
    // 2 设置请求的相关信息: 需要根据请求方式分别设置
    //  统一保存数据
    var data = urlencoded(options.data);
    //  2.1 将请求方式统一转换为大写(或小写)
    var type = options.type.toUpperCase();
    //  2.2 对请求方式进行检测
    if (type === 'GET') {
        xhr.open('GET', options.url + '?' + data);
        xhr.send();
    } else if (type === 'POST') {
        xhr.open('POST', options.url);
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        xhr.send(data);
    }
    // 3 设置事件接收响应内容
    xhr.onreadystatechange = function () {
        // 3.1 检测
        if (xhr.readyState === 4 && xhr.status === 200) {
            // 3.2 将JSON格式的字符串转换为对象
            var res = JSON.parse(xhr.responseText);
            options.success(res);
        }
    };
}

// 进行数据处理的函数
function urlencoded(obj) {
    var arr = []; // 声明数组用来保存结果
    // 遍历obj,获取所有属性
    for (var k in obj) {
        // k - 属性名 - 字符串类型
        // obj[k] - 属性值
        arr.push(k + '=' + obj[k]);
    }
    return arr.join('&');
}
可选:可以给ajax函数的options中的属性设置默认值

- type默认值为'GET'
- data默认为''
- success如果不存在,则不进行调用,避免报错

18. XMLHttpRequest Level2的新功能

可以设置 HTTP 请求的时限

可以使用 FormData 对象管理表单数据

可以上传文件

可以获得数据传输的进度信息

18.1. 设置HTTP请求时限

设置方式:

  • 属性: xhr.timeout = 超时时间; // 毫秒单位
  • 时间: xhr.ontimeout = function() { 请求超时后,触发的事件 };
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks');

// 设置请求的超时时间(毫秒单位)
xhr.timeout = 500;

// 设置事件,对超时进行处理
xhr.ontimeout = function () {
    console.log('网络开小差了,请稍后再试!~');
};
xhr.send();
xhr.onreadystatechange = function () {
    if (xhr.readyState === 4 && xhr.status === 200) {
        console.log(xhr.responseText);
    }
};

18.2. FormData管理表单数据

FormData的作用:

  • 可以快速处理表单的数据
  • 可以进行文件上传

注意点:

  • 发送FormData需要使用POST请求方式
  • 不需要单独设置Content-Type

使用方式:

1.单独发送数据:创建空FormData对象,添加数据后发送

// 1.1 创建FormData对象
var fd = new FormData(); // 空的FormData对象
// 1.2 向fd中添加一些数据
fd.append('name', 'jack');
fd.append('age', 18);

// 1.3 使用POST方法将fd发送到对应接口(此处的接口为formdata)
//  无需设置之前post的content-type
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://www.liulongbin.top:3006/api/formdata');
xhr.send(fd); // 将fd放入在send()参数中即可
xhr.onreadystatechange = function () {
    if (xhr.readyState === 4 && xhr.status === 200) {
        console.log(xhr.responseText);
    }
};

2.处理表单数据:通过form表单获取数据后发送

<!-- 设置form标签,用来进行formdata操作 -->
    <form id="testForm">
        <!-- 如果要表单元素数据被请求发送,必须设置name -->
        <input type="text" name="username">
        <input type="password" name="password">
        <!-- 设置按钮,点击后,使用FormData处理表单数据 -->
        <button type="button" id="btn">ajax提交</button>
    </form>

// 2 通过FormData对象管理表单元素,再发送(同时也可以添加数据)
document.getElementById('btn').onclick = function () {
    // 2.1 创建FormData对象,传入DOM对象形式的form标签到参数中
    var testForm = document.getElementById('testForm');
    var fd = new FormData(testForm); // 空的FormData对象

    // 2.1.1 也可以在存在form的基础上,自己添加数据
    fd.append('name', 'rose');
    fd.append('age', 21);

    // 2.3 使用POST方法将fd发送到对应接口(此处的接口为formdata)
    //  - 无需设置之前post的content-type
    var xhr = new XMLHttpRequest();
    xhr.open('POST', 'http://www.liulongbin.top:3006/api/formdata');
    xhr.send(fd); // 将fd放入在send()参数中即可
    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4 && xhr.status === 200) {
            console.log(xhr.responseText);
        }
    };
}

18.3. 文件上传

  • 1 准备结构(文件域)
<input type="file">
  • 2 检测用户是否选择了文件
    • 对DOM对象形式的input[type="file"]files属性进行检测
      • 如果内部存储了任意的一个值,就说明选取了文件,否则就是没选
  • 3 使用FormData保存文件信息
    • 使用fd.append()添加即可
  • 4 通过ajax发送
  • 5 响应处理,展示服务端获取到的图片
    <input type="file" id="iptFile">
    <button type="button" id="btn">点击上传文件</button>
    <img src="" alt="" id="pic">
    
    // 1 给按钮设置点击事件
    var btn = document.getElementById('btn');
    var iptFile = document.querySelector('#iptFile');
    var pic = document.getElementById('pic');
    
    btn.onclick = function () {
      // 2 检测是否上传了文件,需要检测文件域的files属性
      //  files是一个伪数组,可以通过判断length,检测是否选择了文件
      if (iptFile.files.length === 0) {
        // 说明没有选择文件
        alert('请选择文件后提交!~');
        return;
      }

      // 3 通过FormData保存文件信息
      var fd = new FormData();
      // avatar是接口中规定的请求参数名称
      // files[0]代表选择的文件的相关信息
      fd.append('avatar', iptFile.files[0]);

      // 4 发送post形式的ajax,将fd发送给服务端处理
      var xhr = new XMLHttpRequest();
      xhr.open('POST', 'http://www.liulongbin.top:3006/api/upload/avatar');
      xhr.send(fd);

      // 5 接收响应数据
      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4 && xhr.status === 200) {
          var res = JSON.parse(xhr.responseText);
          // 5.1 检测上传是否成功
          if (res.status === 200) {
            // 5.2 将响应的图片在线地址,放入到img中展示
            pic.src = 'http://www.liulongbin.top:3006' + res.url
          }
        }
      }
    };

jQuery使用FormData上传文件的注意点

  • 必须设置两个属性
    • contentType: false 不指定内容类型
    • processData: false 不进行数据处理

18.4. 上传进度条功能

xhr.upload.onprogress 上传中实时触发事件

事件对象e的属性

  • e.lengthComputable 是一个布尔值,表示当前上传的资源是否具有可计算的长度
  • e.loaded 已传输的字节
  • e.total 需传输的总字节

xhr.upload.onload 上传完毕时触发事件

/*
      1 检测上传过程的事件
        xhr.upload.onprogress = function(e) ...
      2 检测文件大小是否可用
        e.lengthComputable 布尔值
      3 计算进度
        e.loaded 已加载的大小
        e.total  总大小
      3.1 计算方式
        e.loaded / e.total 上传的进度

      制作进度条功能的思路:
        - 设置内外两个盒子,外部盒子定宽度,内部盒子宽度默认为0
        - 上传中,根据上传的进度设置内部盒子宽度对应改变即可

      xhr.upload.onload 上传完毕后触发的事件
    */

var btn = document.getElementById('btn');
var iptFile = document.querySelector('#iptFile');
var pic = document.getElementById('pic');

btn.onclick = function () {
    // 2 检测是否上传了文件,需要检测文件域的files属性
    if (iptFile.files.length === 0) {
        alert('请选择文件后提交!~');
        return;
    }

    // 3 通过FormData保存文件信息
    var fd = new FormData();
    fd.append('avatar', iptFile.files[0]);

    // 4 发送post形式的ajax,将fd发送给服务端处理
    var xhr = new XMLHttpRequest();

    // 设置上传文件的进度监测
    xhr.upload.onprogress = function (e) {
        // 判断e.lengthComputable是否为true,为true表示可以进行计算
        if (e.lengthComputable) {
            // 根据e.loaded和e.total计算进度比例
            var bili = e.loaded / e.total * 100 + '%';
            document.getElementById('percent').style.width = bili;
            document.getElementById('percent').innerText = bili;
        }
    };

    // 设置上传文件完成的事件(更改样式)
    xhr.upload.onload = function () {
        document.getElementById('percent').className = 'progress-bar progress-bar-success';
    }

    xhr.open('POST', 'http://www.liulongbin.top:3006/api/upload/avatar');
    xhr.send(fd);

    // 5 接收响应数据
    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4 && xhr.status === 200) {
            var res = JSON.parse(xhr.responseText);
            // 5.1 检测上传是否成功
            if (res.status === 200) {
                // 5.2 将响应的图片在线地址,放入到img中展示
                console.log(res);
            }
        }
    }
};

19. jQuery的全局ajax处理器

作用:用来对页面中的ajax操作进行统一设置,简化操作

常见场景:加载资源的loading功能

ajaxStart() 任意请求开始时触发内部回调

//使用全局ajax处理器检测请求发送的操作,并将loading图展示
$(document).ajaxStart(function () {
    // console.log('发送了ajax请求');
    $('img').show();
});

ajaxStop() 任意请求结束后触发内部回调

//使用全局ajax处理器检测请求完毕的状态,并将loading图隐藏
$(document).ajaxStop(function () {
    $('img').hide();
});

在ajax内部自己封装加载资源的loading功能

$("#btn").on("click", function() {
    $("img").show();       //在请求开始之前将loading图展示
    $.ajax({
        url: "http://www.liulongbin.top:3006/api/getbooks",
        success: function(res) {
            $(".box").html(JSON.stringify(res));
            $("img").hide();      //请求完毕,并将loading图隐藏
        }
    })
})

20. 同源策略和跨域

20.1. 同源(同源地址)

指的是两个页面地址的 协议 域名 端口 完全一样,这两个地址就是同源的,或者称为同源地址。

  • 我们发现,在现代网站中(京东)一个公司可能具有很多的域名,也都不是同源地址,如果在公司内部都不能进行数据请求,是很不方便的。

20.2. 同源策略

同源策略(英文全称 Same origin policy)是浏览器提供的一个安全功能。

同源策略不允许和非同源的网站之间发送ajax请求

发送跨域请求时,请求发送是成功的,响应也是成功的,只不过浏览器将响应的信息拦截了,我们无法操作。

  • 对我们操作的影响,无法对非同源的地址发送ajax请求(不能跨域)

20.3. 跨域

跨域指的是非同源网站之间发送ajax请求

现在,实现跨域数据请求,最主要的两种解决方案,分别是 JSONP 和 CORS。

JSONP

兼容性好,但是只支持GET

CORS

兼容性不太好,但是支持GET、POST,并且是标准中提供的方式。

20.4. 跨域方式-JSONP

JSONP:出现的早,兼容性好(兼容低版本IE)。是前端程序员为了解决跨域问题,被迫想出来的一种临时解决方案。缺点是只支持 GET 请求,不支持 POST 请求。

JSONP (JSON with Padding) 是 JSON 的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。

由于浏览器同源策略的限制,网页中无法通过 Ajax 请求非同源的接口数据。

但是 <script> 标签不受浏览器同源策略的影响,可以通过 src 属性,请求非同源的 js 脚本。

  • JSONP 的实现原理:

通过 <script>标签的 src 属性,请求跨域的数据接口,并通过函数调用的形式,接收跨域接口响应回来的数据。

同源策略不限制script标签对非同源地址进行请求

可以借助script标签进行JSONP实现

<!-- 
使用JSONP进行请求处理
步骤:
1 准备一个处理函数
2 通过script标签的src属性,进行接口的请求
    - 因为同源策略不会限制script标签的功能
3 请求时传入请求参数
    - callback 用来传递本地处理函数的函数名
        - 其他参数随便写
4 当响应结束后,步骤1设置的处理函数会自动调用
    - 可以在处理函数中对响应数据进行后续处理
-->
<script>
    function fun(res) {
    console.log(res);
}
</script>
<script src="http://ajax.frontend.itheima.net:3006/api/jsonp?callback=fun&name=jack"></script>

说明:

  • JSONP和JSON没有本质关联
  • JSONP与ajax没有任何关联
    • JSONP是使用script标签的src属性进行请求发送
    • ajax是通过浏览器提供的XMLHttpRequest对象发送请求

20.5. 跨域方式-CORS

CORS:出现的较晚,它是 W3C 标准,属于跨域 Ajax 请求的根本解决方案。支持 GET 和 POST 请求。缺点是不兼容某些低版本的浏览器。

20.6. jQuery发送JSONP请求的方式

jQuery 中的 JSONP,也是通过 <script> 标签的 src 属性实现跨域数据访问的,

只不过,jQuery 采用的是动态创建和移除 <script>标签的方式,来发起 JSONP 数据请求。

在发起 JSONP 请求的时候,动态向 <header> 中 append 一个<script> 标签;

在 JSONP 请求成功以后,动态从 <header>中移除刚才 append 进去的 <script> 标签;

jQuery使用的是$.ajax()方法进行JSONP操作,

  • 设置dataType属性为’jsonp’

  • 说明:

    • 可以从浏览器的network看到请求的类型为 script
    • jQuery会将使用过的用于发送jsonp请求的script标签移除,打开页面也看不到
$.ajax({
    type: 'GET',
    url: 'http://ajax.frontend.itheima.net:3006/api/jsonp',
    data: {
        name: 'jack',
        age: 18
    },

    // 下面的两个属性作为了解即可,通常不会使用
    //jsonp: 'xyz',          // 将默认的请求参数名callback设置为其他名称
    //jsonpCallback: 'abc',  // 将处理函数名称设置为指定名称

    dataType: 'jsonp',      // 设置这句话后,jQuery就会使用JSONP的方式进行请求发送
    success: function (res) {
        console.log(res);
    }
});

21. 防抖和节流

21.1. 防抖

防抖策略(debounce)是当事件被触发后,延迟 n 秒后再执行回调,如果在这 n 秒内事件又被触发,则重新计时。

进行重复操作时,设置时间间隔,以最后一次满足间隔的操作为准进行执行。

简单来说:就是以满足间隔的最后一次为准执行事件

应用场景 :用户在输入框中连续输入一串字符时,可以通过防抖策略,只在输入完后,才执行查询的请求,这样可以有效减少请求次数,节约请求资源。设置防抖操作可以减少页面中不必要的请求次数

// --- 设置防抖功能
var timer = null; // 用来保存进行防抖操作的定时器id

// 设置事件
$('#ipt').on('keyup', function () {
    // --- 如果再次输入,将上次的定时器清除即可
    clearTimeout(timer);

    // --- 通过定时器控制
    timer = setTimeout(function () {
        getData(val);
    }, 100);
});

// 封装函数,用来进行数据请求
function getData(val) {
    $.ajax({
        url: 'https://suggest.taobao.com/sug',
        data: { q: val },// 淘宝的这个接口指定了请求参数名为q,代表要查询的内容
        dataType: 'jsonp', // 使用jsonp方式发送请求
        success: function (res) {
            // 3 检测数据并创建结构(封装为函数,在多个地方使用)
            renderList(res);
        }
    });
}

21.2. 节流

节流策略(throttle),顾名思义,可以减少一段时间内事件的触发频率。

概念:也可以称为函数节流,目的是减少某些操作的触发速度

节流的应用场景 :mousemove事件 scroll等事件

鼠标连续不断地触发某事件(如点击),只在单位时间内只触发一次事件;

懒加载时要监听计算滚动条的位置,但不必每次滑动都触发,可以降低计算的频率,而不必去浪费 CPU 资源

//让操作以指定间隔执行
//通过定时器进行设置
//在指定的时间间隔内再次触发操作会被忽略
//直到本次操作完毕,才允许执行下一次
<body>
  <img src="./angel.gif" alt="" id="angel" />
  <script>
    // 我们希望mousemove事件执行间隔变大,至少为100ms,可以使用节流操作
    var flag = true; // 默认为true代表可以执行操作

    // 1 设置鼠标移动事件
    $(document).on('mousemove', function (e) {
      if (flag !== true) {
        return;
      }
      flag = false; // 设置下次无法触发
      setTimeout(function () {
        // 2 将鼠标的横纵坐标设置给img的left和top即可
        $('#angel').css({
          left: e.pageX,
          top: e.pageY
        });
        flag = true; // 本次间隔后操作执行后,允许进行下次操作
      }, 20);
    });
  </script>
</body>

21.3. 节流和防抖的区别:

防抖是当指定间隔时间内再次触发,使用新触发的操作再次重新记时。

节流是在指定间隔时间内再次触发,新操作会被忽略。

防抖:如果事件被频繁触发,防抖能保证只有最后一次触发生效!前面 N 多次的触发都会被忽略!

节流:如果事件被频繁触发,节流能够减少事件触发的频率,因此,节流是有选择性地执行一部分事件!

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值