一.原生AJAX

1 AJAX简介

AJAX 全称为 Asynchronous JavaScript And XML,就是异步的 JS 和 XML。
通过 AJAX 可以在浏览器中向服务器发送异步请求,最大的优势:无需刷新获取数据。
AJAX 不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式。

1.2 XML简介

  • XML可扩展标记语言
  • XML被用来传输和储存数据
  • XML 和 HTML 类似,不同的是 HTML 中都是预定义标签,而 XML中没有预定义标签 ```xml 比如说我有一个学生数据: name = “孙悟空” ; age = 18 ; gender = “男” ;

用 XML 表示:

孙悟空 18

用 JSON 表示: {“name”:”孙悟空”,”age”:18,”gender”:”男”}

  1. <a name="K7Xed"></a>
  2. ## 1.3 AJAX的特点
  3. <a name="OdDpo"></a>
  4. ### 1.3.1 AJAX的优点
  5. 1. 可以无需刷新页面而与服务器端进行通信。
  6. 1. 允许你根据用户事件来更新部分页面内容。
  7. <a name="JstLh"></a>
  8. ### 1.3.2 AJAX的缺点
  9. 1. 没有浏览历史,不能回退
  10. 1. 存在跨域问题(同源)
  11. 1. SEO(搜索引擎优化)不友好
  12. ---
  13. <a name="5RY1w"></a>
  14. ## 1.4 AJAX的使用
  15. <a name="V5Ixn"></a>
  16. ### 1.4.1 核心对象
  17. XMLHttpRequest,AJAX 的所有操作都是通过该对象进行的。
  18. <a name="dvnXe"></a>
  19. ### 1.4.2 使用步骤
  20. ```javascript
  21. //1. 创建对象
  22. const xhr = new XMLHttpRequest();
  23. //2.设置请求信息 请求方法和 url
  24. xhr.open('GET', 'http://localhost:8000/server?a=100&b=200&c=300');
  25. //可以设置请求头,一般不设置
  26. xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  27. //3. 发送请求 get 请求不传 body 参数,只有 post 请求使用
  28. xhr.send();
  29. //4. 事件绑定 处理服务端返回的结果
  30. // readystate 是 xhr 对象中的属性, 表示状态 0 1 2 3 4 一般使用状态4作为判断
  31. /*0: 表示 XMLHttpRequest 实例已经生成,但是 open()方法还没有被调用。
  32. 1: 表示 send()方法还没有被调用,仍然可以使用 setRequestHeader(),设定 HTTP 请求的头信息。
  33. 2: 表示 send()方法已经执行,并且头信息和状态码已经收到。
  34. 3: 表示正在接收服务器传来的 body 部分的数据。
  35. 4: 表示服务器数据已经完全接收,或者本次接收已经失败了*/
  36. xhr.onreadystatechange = function(){
  37. //判断 (服务端返回了所有的结果)
  38. if(xhr.readyState === 4){
  39. //判断响应状态码 200 404 403 401 500
  40. // 2xx 成功
  41. if(xhr.status >= 200 && xhr.status < 300){
  42. //处理结果 行 头 空行 体
  43. //响应
  44. // console.log(xhr.status);//状态码
  45. // console.log(xhr.statusText);//状态字符串
  46. // console.log(xhr.getAllResponseHeaders());//所有响应头
  47. // console.log(xhr.response);//响应体
  48. //设置 result 的文本
  49. result.innerHTML = xhr.response;
  50. }
  51. }
  52. }

JSON响应方式

  1. const result = document.getElementById('result');
  2. //绑定键盘按下事件
  3. window.onkeydown = function(){
  4. //发送请求
  5. const xhr = new XMLHttpRequest();
  6. //设置响应体数据的类型
  7. xhr.responseType = 'json';
  8. //超时设置 2s 设置
  9. xhr.timeout = 2000;
  10. //初始化
  11. xhr.open('GET','http://127.0.0.1:8000/json-server');
  12. //发送
  13. xhr.send();
  14. //事件绑定
  15. xhr.onreadystatechange = function(){
  16. if(xhr.readyState === 4){
  17. if(xhr.status >= 200 && xhr.status < 300){
  18. // console.log(xhr.response);
  19. // result.innerHTML = xhr.response;
  20. // 1. 手动对数据转化
  21. // let data = JSON.parse(xhr.response);
  22. // console.log(data);
  23. // result.innerHTML = data.name;
  24. // 2. 自动转换
  25. console.log(xhr.response);
  26. result.innerHTML = xhr.response.name;
  27. }
  28. }
  29. }
  30. }

超时与网络异常

  1. btn.addEventListener('click', function(){
  2. const xhr = new XMLHttpRequest();
  3. //超时设置 2s 设置
  4. xhr.timeout = 2000;
  5. //超时回调
  6. xhr.ontimeout = function(){
  7. alert("网络异常, 请稍后重试!!");
  8. }
  9. //网络异常回调
  10. xhr.onerror = function(){
  11. alert("你的网络似乎出了一些问题!");
  12. }
  13. xhr.open("GET",'http://127.0.0.1:8000/delay');
  14. xhr.send();
  15. xhr.onreadystatechange = function(){
  16. if(xhr.readyState === 4){
  17. if(xhr.status >= 200 && xhr.status< 300){
  18. result.innerHTML = xhr.response;
  19. }
  20. }
  21. }
  22. })
  23. //后端代码 node
  24. //延时响应
  25. app.all('/delay', (request, response) => {
  26. //设置响应头 设置允许跨域
  27. response.setHeader('Access-Control-Allow-Origin', '*');
  28. response.setHeader('Access-Control-Allow-Headers', '*');
  29. setTimeout(() => {
  30. //设置响应体
  31. response.send('延时响应');
  32. }, 1000)
  33. });

取消重复请求

  1. //获取元素对象
  2. const btns = document.querySelectorAll('button');
  3. let x = null;
  4. //标识变量
  5. let isSending = false; // 是否正在发送AJAX请求
  6. btns[0].onclick = function(){
  7. //判断标识变量
  8. if(isSending) x.abort(); // 如果正在发送, 则取消该请求, 创建一个新的请求
  9. x = new XMLHttpRequest();
  10. //修改 标识变量的值
  11. isSending = true;
  12. x.open("GET",'http://127.0.0.1:8000/delay');
  13. x.send();
  14. x.onreadystatechange = function(){
  15. if(x.readyState === 4){
  16. //修改标识变量
  17. isSending = false;
  18. }
  19. }
  20. }
  21. // abort
  22. btns[1].onclick = function(){
  23. //取消请求
  24. x.abort();
  25. }

1.4.3 解决 IE 缓存问题

  • 问题:在一些浏览器中(IE),由于缓存机制的存在,ajax 只会发送的第一次请求,剩余多次请求不会在发送给浏览器而是直接加载缓存中的数据。
  • 解决方式:浏览器的缓存是根据 url 地址来记录的,所以我们只需要修改 url 地址即可避免缓存问题
    1. //设置请求信息
    2. xhr.open("GET",'http://127.0.0.1:8000/ie?t='+Date.now());

二.jQuery-AJAX

  1. $('button').eq(0).click(function(){
  2. $.get('http://127.0.0.1:8000/jquery-server', {a:100, b:200}, function(data){
  3. console.log(data);
  4. },'json');
  5. });
  6. $('button').eq(1).click(function(){
  7. $.post('http://127.0.0.1:8000/jquery-server', {a:100, b:200}, function(data){
  8. console.log(data);
  9. });
  10. });
  11. $('button').eq(2).click(function(){
  12. $.ajax({
  13. //url
  14. url: 'http://127.0.0.1:8000/jquery-server',
  15. //参数
  16. data: {a:100, b:200},
  17. //请求类型
  18. type: 'GET',
  19. //响应体结果
  20. dataType: 'json',
  21. //成功的回调
  22. success: function(data){
  23. console.log(data);
  24. },
  25. //超时时间
  26. timeout: 2000,
  27. //失败的回调
  28. error: function(){
  29. console.log('出错啦!!');
  30. },
  31. //头信息
  32. headers: {
  33. c:300,
  34. d:400
  35. }
  36. });
  37. });

三.axios-AJAX

文档地址 https://github.com/axios/axios

  1. const btns = document.querySelectorAll('button');
  2. //配置 baseURL
  3. axios.defaults.baseURL = 'http://localhost:8083';
  4. btns[0].onclick = function () {
  5. //GET 请求
  6. axios.get('/axios-server', {
  7. //url 参数
  8. params: {
  9. id: 100,
  10. vip: 7
  11. },
  12. //请求头信息
  13. headers: {
  14. name: 'atguigu',
  15. age: 20
  16. }
  17. }).then(value => {
  18. console.log(value);//返回promise对象
  19. });
  20. }
  21. //post发送方式 第二个参数请求体
  22. btns[1].onclick = function () {
  23. axios.post('/axios-server', {
  24. username: 'admin',
  25. password: 'admin'
  26. }, {
  27. //url
  28. params: {
  29. id: 200,
  30. vip: 9
  31. },
  32. //请求头参数
  33. headers: {
  34. height: 180,
  35. weight: 180,
  36. }
  37. });
  38. }
  39. btns[2].onclick = function(){
  40. axios({
  41. //请求方法
  42. method : 'POST',
  43. //url
  44. url: '/axios-server',
  45. //url参数
  46. params: {
  47. vip:10,
  48. level:30
  49. },
  50. //头信息
  51. headers: {
  52. a:100,
  53. b:200
  54. },
  55. //请求体参数
  56. data: {
  57. username: 'admin',
  58. password: 'admin'
  59. }
  60. }).then(response=>{
  61. //响应状态码
  62. console.log(response.status);
  63. //响应状态字符串
  64. console.log(response.statusText);
  65. //响应头信息
  66. console.log(response.headers);
  67. //响应体
  68. console.log(response.data);
  69. })
  70. }

四. fetch-AJAX

文档地址:https://developer.mozilla.org/zh-CN/docs/Web/API/WindowOrWorkerGlobalScope/fetch

  1. const btn = document.querySelector('button');
  2. btn.onclick = function(){
  3. fetch('http://localhost:8000/fetch-server?id=1', {
  4. //请求方法
  5. method: 'POST',
  6. //请求头
  7. headers: {
  8. name:'atguigu'
  9. },
  10. //请求体
  11. body: 'username=admin&password=admin'
  12. }).then(response => {
  13. // return response.text();
  14. return response.json();
  15. }).then(response=>{
  16. console.log(response);
  17. });
  18. }

五.跨域

5.1同源策略

同源策略(Same-Origin Policy)最早由 Netscape 公司提出,是浏览器的一种安全策略。
同源: 协议、域名、端口号 必须完全相同。
违背同源策略就是跨域。
前端页面代码:

  1. const btn = document.querySelector('button');
  2. btn.onclick = function(){
  3. const x = new XMLHttpRequest();
  4. //这里因为是满足同源策略的, 所以 url 可以简写
  5. x.open("GET",'/data');
  6. //发送
  7. x.send();
  8. //
  9. x.onreadystatechange = function(){
  10. if(x.readyState === 4){
  11. if(x.status >= 200 && x.status < 300){
  12. console.log(x.response);
  13. }
  14. }
  15. }
  16. }

服务代码:

  1. const express = require('express');
  2. const app = express();
  3. app.get('/home', (request, response)=>{
  4. //响应一个页面
  5. response.sendFile(__dirname + '/index.html');
  6. });
  7. app.get('/data', (request, response)=>{
  8. response.send('用户数据');
  9. });
  10. app.listen(9000, ()=>{
  11. console.log("服务已经启动...");
  12. });

5.2 JSONP

5.2.1 JSONP 是什么

JSONP 是什么 JSONP(JSON with Padding),是一个非官方的跨域解决方案,纯粹凭借程序员的聪明 才智开发出来,只支持 get 请求。

5.2.2 JSONP 怎么工作的?

在网页有一些标签天生具有跨域能力,比如:img link iframe script。
JSONP 就是利用 script 标签的跨域能力来发送请求的。

5.2.3 JSONP 的使用

其实就是服务端返回一个函数 ,前端浏览器解析这个函数并且提前定义了

  1. //1. 创建 script 标签
  2. const script = document.createElement('script');
  3. //2. 设置标签的 src 属性
  4. script.src = 'http://127.0.0.1:8000/check-username';
  5. //3. 将 script 插入到文档中
  6. document.body.appendChild(script);
  7. 4.服务器中路由的处理
  8. app.all('/check-username',(request, response) => {
  9. // response.send('console.log("hello jsonp")');
  10. const data = {
  11. exist: 1,
  12. msg: '用户名已经存在'
  13. };
  14. //将数据转化为字符串
  15. let str = JSON.stringify(data);
  16. //返回结果
  17. response.end(`handle(${str})`);
  18. });

5.3 CORS

5.3.1 CORS 介绍

CORS(Cross-Origin Resource Sharing),跨域资源共享。CORS 是官方的跨域解决方案,它的特点是不需要在客户端做任何特殊的操作,完全在服务器中进行处理,支持 get 和 post 请求。
跨域资源共享标准新增了一组 HTTP 首部字段,允许服务器声明哪些 源站通过浏览器有权限访问哪些资源

5.3.2 CORS 怎么工作的?

CORS 是通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器收到该响应 以后就会对响应放行。

5.3.3 CORS 的使用主要是服务器端的设置:

  1. //设置响应头
  2. response.setHeader("Access-Control-Allow-Origin", "*");
  3. response.setHeader("Access-Control-Allow-Headers", '*');
  4. response.setHeader("Access-Control-Allow-Method", '*');
  5. // response.setHeader("Access-Control-Allow-Origin", "http://127.0.0.1:5500"); 指定请求源