前端核心四:AJAX

*★如果文章对你有帮助【关注点赞❤️收藏⭐】一起努力!★*

‍ 个人主页:花棉袄

本章内容:【前端核心五:AJAX学习视频推荐
✍ 版权: 本文由【花棉袄】原创在CSDN首发需要转载请联系博主

AJAX简介

1️⃣AJAX简介

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

2️⃣AJAX特点

AJAX 的优点
  可以无需刷新页面而与服务器端进行通信
  允许你根据用户事件来更新部分页面内容

AJAX 的缺点
  没有浏览历史,不能回退
  存在跨域问题(同源)
  SEO(Search Engine Optimization,搜索引擎优化)不友好,爬虫无法爬取


HTTP协议

HTTP(hypertext transport protocol)协议「超文本传输议」
协议详细规定了浏览器和万维网服务器之间互相通信的规则

1️⃣请求报文

请求行
  请求类型:GET/POST/PUT/DELETE/PATCH
  URL 路径:s?ie=utf-8
  HTTP 协议版本:HTTP/1.1

请求头
  Host: atguigu.com
  Cookie: name=guigu
  Content-type: application/x-www-form-urlencoded
  User-Agent: chrome 83
  …

前端核心四:AJAX_第1张图片

请求空行:固定格式,必须有

请求体:GET请求,请求体为空;POST请求,请求体可以不为空
  username=admin&password=admin

前端核心四:AJAX_第2张图片

2️⃣响应报文

响应行
  HTTP 协议版本:HTTP/1.1
  响应状态码:200/404/500
  响应状态字符串:OK/Not Found/Internal Server Error,与响应状态码对应

响应头
  Content-Type: text/html;charset=utf-8
  Content-length: 2048
  Content-encoding: gzip
  …

前端核心四:AJAX_第3张图片

响应空行 :固定格式,必须有

响应体

前端核心四:AJAX_第4张图片

3️⃣状态码

1xx:Informational(信息性状态码) 请求正在处理
2xx:Success(成功状态码) 请求正常处理完毕
3xx:Redirection(重定向) 需要进行附加操作以完成请求
4xx:Client error(客户端错误) 客户端请求出错
5xx:Server Error(服务器错误) 服务器处理请求出错

4️⃣响应状态码

200 OK 请求成功
302 Found 请求资源的 URL 被暂时修改到 Location 提供的 URL
304 Not Modified 资源未变更
308 Permanent Redirect 永久重定向
400 Bad Request 请求语法有问题,服务器无法识别
401 UnAuthorized 客户端未授权该请求
403 Forbidden 服务器拒绝响应
404 Not Found URL 无效或者 URL 有效但是没有资源
500 Internal Server Error 服务器内部错误
502 Bad Gateway 服务器作为网关使用时,收到上游服务器返回的无效响应
503 Service Unavailable 无法服务,一般发生在因维护而停机或者服务过载
504 Gateway Timeout 网关超时
505 Http Version Not Supported 发出的请求http版本服务器不支持


开发准备

安装 Node.js

1️⃣使用Express

# 初始化
npm init --yes
# 安装express框架
npm i express
// 1、引入express
// const express = require('express');
import express from 'express';

// 2、创建应用对象
const app = express();

// 3、创建路由规则
// request 请求报文的封装
// response 响应报文的封装
app.get('/', (request, response) => {
    // 设置响应
    response.send('Hello Express');
});

// 4、监听端口启动服务
app.listen(8000, () => {
    console.log("服务已经启动,8000 端口监听中...");
});

键入命令 node js文件名
出现服务已经启动,8000 端口监听中…字样,说明启动成功
我们打开浏览器,访问 http://127.0.0.1:8000,出现Hello Express字样

2️⃣简单案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <style>
        #result {
            width: 200px;
            height: 100px;
            border: 1px solid #90b;
        }
    </style>

    <button>点击发送</button>
    <div id="result"></div>
</body>
</html>

3️⃣发送 GET 请求

// 1、引入express
// const express = require('express');
import express from 'express';

// 2、创建应用对象
const app = express();

// 3、创建路由规则
// request 请求报文的封装
// response 响应报文的封装
app.get('/server', (request, response) => {
      // 设置响应头,设置允许跨域
      response.setHeader('Access-Control-Allow-Origin', '*');
    // 设置响应体
    response.send('Hello AJAX');
});

// 4、监听端口启动服务
app.listen(8000, () => {
    console.log("服务已经启动,8000 端口监听中...");
});

创建对象

const xhr = new XMLHttpRequest();

初始化

xhr.open('GET', 'http://127.0.0.1:8000/server');

发送

xhr.send();

事件绑定,处理服务器端返回的结果

xhr.onreadystatechange = function () {...}
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>AJAX发送Get请求</title>
</head>
<body>
    <style>
        #result {
            width: 200px;
            height: 100px;
            border: 1px solid #90b;
        }
    </style>
    <button>点击发送</button>
    <div id="result"></div>
    <script>
        const result = document.getElementById('result');
        const button = document.getElementsByTagName("button")[0];
        button.onclick = function () {
            // 1、创建对象
            const xhr = new XMLHttpRequest();
            // 2、初始化
            xhr.open('GET', 'http://127.0.0.1:8000/server');
            // 3、发送
            xhr.send();
            // 4、事件绑定,处理服务器端返回的结果
            xhr.onreadystatechange = function () {
                // 服务端返回所有结果
                if (this.readyState === 4) {
                    // 2xx 成功
                    if (this.status >= 200 && this.status < 300) {
                        // 状态码、状态字符串
                        console.log("status:" + this.status); // 200
                        console.log("statusText:" + this.statusText); // OK
                        // 响应头
                        console.log("Headers:" + this.getAllResponseHeaders()); // content-length: 13  content-type: text/html; charset=utf-8
                        // 响应体
                        console.log("response:" + this.response); // Hello Express
                        // 将响应体内容设置为文本
                        result.innerHTML = this.response;
                    }
                }
            }
        };
    </script>
</body>
</html>

前端核心四:AJAX_第5张图片

GET 设置请求行

xhr.open('GET', 'http://127.0.0.1:8000/server?a=100&b=200&c=300');

4️⃣发送 POST 请求

// 1、引入express
// const express = require('express');
import express from 'express';

// 2、创建应用对象
const app = express();

// 3、创建路由规则
// request 请求报文的封装
// response 响应报文的封装
app.post('/server', (request, response) => {
      // 设置响应头,设置允许跨域
      response.setHeader('Access-Control-Allow-Origin', '*');
    // 设置响应体
    response.send('Hello AJAX');
});

// 4、监听端口启动服务
app.listen(8000, () => {
    console.log("服务已经启动,8000 端口监听中...");
});
    <script>
        const result = document.getElementById('result');
        result.addEventListener('mouseover', function () {
            const xhr = new XMLHttpRequest();
            xhr.open('POST', 'http://127.0.0.1:8000/server');
            xhr.send();
            xhr.onreadystatechange = function () {
                if (this.readyState === 4 && this.status >= 200 && this.status < 300) {
                    result.innerHTML = this.response;
                }
            };
        });
    </script>

前端核心四:AJAX_第6张图片

POST 设置请求体

xhr.send('a=100&b=200&c=300');

5️⃣设置请求头信息

设置请求头信息

xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');

自定义的请求头

xhr.setRequestHeader('name', 'atguigu');
app.all('/server', (request, response) => {
    // 设置响应头,允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    // 设置响应头,允许任意类型的头信息
    response.setHeader('Access-Control-Allow-Headers', '*');
    // 设置响应体
    response.send('Hello Express');
});

6️⃣响应 JSON 数据

const data = {
    name:'Hello Ajax'
}
let str = JSON.stringify(data);
response.send(str);

前端核心四:AJAX_第7张图片

手动转换数据

let response = this.response;
console.log(typeof response); // string
data = JSON.parse(response);
result.innerHTML = data.name;

前端核心四:AJAX_第8张图片


自动重启工具

官网地址:https://www.npmjs.com/package/nodemon
安装命令npm install -g nodemon
启动命令:nodemon xxx.js替代node xxx.js
优点:修改服务端代码不用每次手动shutdown重启

前端核心四:AJAX_第9张图片


请求超时

1️⃣请求超时

# js文件
setTimeout(() =>{
    response.send('Hello Ajax');
}, 2000);
# html文件
// 设置超时时间
xhr.timeout = 1000;
// 设置超时回调
xhr.ontimeout = () => {
    alert('请求超时!');
};

2️⃣网络异常

# html 文件
// 设置网络异常回调
xhr.onerror = () => {
    alert("网络异常");
};

手动取消请求

abort()方法:手动取消请求

const btns = document.getElementsByTagName('button');
const btn1 = btns[0];
const btn2 = btns[1];

let xhr = null;
btn1.addEventListener('click', () => {
    xhr = new XMLHttpRequest();
    xhr.open('GET', 'http://127.0.0.1:8000/server-timeout');
    xhr.send();
});
btn2.addEventListener('click', () => {
    xhr.abort();
});

请求重复发送

如果服务器响应相对比较慢,而用户因为得不到响应而频繁地点击按钮
浏览器短时间内会向服务器发起大量重复的请求
服务器就要对这些请求进行频繁的处理
服务器端的压力就会非常的大

const btns = document.getElementsByTagName('button');
let xhr = null;
// 标识是否正在发送 AJAX 请求
let isSending = false;
btns[0].addEventListener('click', () => {
    // 若上一个请求尚未完成,则手动取消请求
    if (isSending) {
        xhr.abort();
    }
    xhr = new XMLHttpRequest();
    isSending = true;
    xhr.open('GET', 'http://127.0.0.1:8000/servertimeout');
    xhr.send();
    xhr.onreadystatechange = () => {
        // 请求响应完毕后,修改变量标识
        if (xhr.readyState === 4) {
            isSending = false;
        }
    };
});

前端核心四:AJAX_第10张图片


JQuery发送AJAX请求

jQuery 脚本

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

bootstrp 脚本

<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.0.2/css/bootstrap.css" rel="stylesheet">

1️⃣GET 请求

$.get(url,[data],[callback],[type])

url:请求的 URL 地址
data:请求携带的参数
callback:载入成功时回调函数
type:设置返回内容格式,xml,html,script,ison,text,_default

btns.eq(0).click(() => {
    $.get('http://127.0.0.1:8000/server-jquery', { a: 100, b: 200 }, (data) => {
        console.log(typeof data, data); // object {name: "Hello jquery"}
    }, 'json');
});

2️⃣POST请求

$.post(url,[data],[callback],[type])

url:请求的 URL 地址
data:请求携带的参数
callback:载入成功时回调函数
type:设置返回内容格式,xml,html,script,ison,text,_default

btns.eq(1).click(() => {
    $.post('http://127.0.0.1:8000/server-jquery', { a: 100, b: 200 }, (data) => {
        console.log(typeof data, data); // string {name: "Hello jquery"}
    },"json");
});

3️⃣通用方法

$.ajax({
    // 请求地址
    url: 'http://127.0.0.1:8000/server-jquery',
    // 请求参数
    data: { a: 100, b: 200 },
    // 请求类型
    type: 'GET',
    // 响应体类型
    dataType: 'json',
    // 成功回调
    success: data => {
        console.log(typeof data, data); // string {name: "Hello jquery"}  开启dataType后:object {name: "Hello jquery"}
    },
    // 超时时间
    timeout: 1000,
    // 失败的回调
    error: () => {
        alert('出错了');
    },
    // 头信息
    headers: {
        c: 300,
        d: 400
    }
});

‍Axios发送AJAX请求

1️⃣GET 请求

 axios#get(url[,config])
  • 函数返回结果是一个promise对象,用then回调处理
axios.defaults.baseURL = 'http://127.0.0.1:8000/';
axios.get('server-axios', {
    // 请求参数
    params: {
        a: 100,
        b: 200
    },
    // 请求头
    headers: {
        c: 300,
        d: 400
    }
}).then(value => {
    console.log(value);
});

2️⃣POST 请求

axios#post(url[,data[,config]])
axios.post('server-axios', {
    // 请求体
		e: 500,
  		f: 600  
}, {
    // 请求参数
    params: {
        a: 100,
        b: 200
    },
    // 请求头
    headers: {
        c: 300,
        d: 400
    }
}).then(value => {
    console.log(value);
});

3️⃣通用方法

axios(url[, config])
axios({
    method: 'POST',
    url: 'server-axios',
    // 请求参数
    params: {
        a: 100,
        b: 200
    },
    // 请求头
    headers: {
        c: 300,
        d: 400
    },
    // 请求体
    data: {
        e: 500,
        f: 600
    },
    // 响应体类型
    dataType: 'json'
}).then(response => {
    console.log(response.status); // 200
    console.log(response.statusText); // OK
    console.log(response.headers); // {content-length: "22", content-type: "text/html; charset=utf-8"}
    console.log(typeof response.data, response.data); // object {name: "Hello axios"}
});

‍Fetch函数发送AJAX请求

fetch('http://127.0.0.1:8000/server-fetch?a=100&b=100', {
    // 请求方法
    method: 'POST',
    // 请求头
    headers: {
        c: 300,
        d: 400
    },
    // 请求体
    body: 'e=500&f=600'
}).then(response => {
    console.log(response);
});
  • 如果我们只想要响应体内容,可以修改then回调
...
.then(response => {
    return response.text();
}).then(response => {
    console.log(typeof response, response); // string {"name":"Hello fetch"}
});
  • 如果明确响应体内容为 json 字符串,可以按如下修改,将会返回一个 object 对象
...
.then(response => {
    return response.json();
}).then(response => {
    console.log(typeof response, response); // object {"name":"Hello fetch"}
});

‍跨域问题

1️⃣同源策略

  • 同源:协议、域名、端口号必须完全相同,违背同源策略就是跨域

2️⃣JSONP的使用

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <style>
       
    </style>
    <button>点击发送</button>
    <div id="result"></div>
    用户名:<input type="text" id="username">
    <p></p>
    <script>
        //声明handle函数
        function handle(data) {
            var input = document.querySelector('input');
            input.style.border = "solid 1px #f00";
            //修改p标签的提示文本
            var p = document.querySelector('p');
            p.innerHTML = data.msg;
        }
    </script>
    <script>
        const input = document.querySelector('input');
        input.onblur = () => {
            let username = this.username;
            // 1、创建一个 script 标签
            var script = document.createElement('script');
            // 2、设置 src 属性
            script.src = 'http://127.0.0.1:8000/check-username';
            // 3、将 script 插入文档中
            document.body.appendChild(script);
        };
    </script>
</body>

</html>
// 1、引入express
// const express = require('express');
import express from 'express';

// 2、创建应用对象
const app = express();

// 3、创建路由规则
// request 请求报文的封装
// response 响应报文的封装
app.all('/check-username', (request, response) => {
  const data = {
      exist: 1,
      msg:'用户名已存在'
  };
  let str = JSON.stringify(data);
  response.end(`handle(${str})`); 
});

// 4、监听端口启动服务
app.listen(8000, () => {
    console.log("服务已经启动,8000 端口监听中...");
});

前端核心四:AJAX_第11张图片

3️⃣JQuery发送JSONP请求

$.getJSON(url,[data],[fn])

url:发送请求地址
data:待发送 key/value 参数
callback:载入成功时回调函数

<button>点击发送请求</button><br><br>
<div id="result"></div>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script>
    $('button').eq(0).click(() => {
        $.getJSON('http://127.0.0.1:8000/server-jsonp-jquery?callback=?', data => {
            $('#result').html(data.msg);
        });
    });
</script>
app.all('/server-jsonp-jquery', (request, response) => {
    const data = {
        exist: 1,
        msg:'用户名已存在'
    };
    let str = JSON.stringify(data);
    response.end(`(${str})`);
});
  • 此时并没有任何输出,但是请求参数中自动生成了一个callback的参数
    在这里插入图片描述
// 接收callback参数
var cb = request.query.callback;
response.end(`${cb}(${str})`);

前端核心四:AJAX_第12张图片

4️⃣跨域资源共享

  • 我们要想进行跨域请求,必须在服务端返回结果时设置允许跨域的响应头
// 设置响应头,允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');

4️⃣响应首部字段

Access-Control-Allow-Origin 指定了允许访问该资源的外域 URI
Access-Control-Expose-Headers 让服务器把允许浏览器访问的头放入白名单
Access-Control-Max-Age 指定了 preflight 请求的结果能够被缓存多久
Access-Control-Allow-Credentials 是否允许浏览器读取 response 的内容
Access-Control-Allow-Methods 指明了实际请求所允许使用的 HTTP 方法
Access-Control-Allow-Headers 指明了实际请求中允许携带的首部字段

  • 一般使用,允许跨域、带有自定义头部信息、任意方法
response.setHeader("Access-Control-Allow-Origin", "*"); 
response.setHeader("Access-Control-Allow-Headers", "*"); 
response.setHeader("Access-Control-A1low-Method", "*");

*★如果文章对你有帮助【关注点赞❤️收藏⭐】一起努力!★*

前端核心四:AJAX_第13张图片
前端核心四:AJAX_第14张图片

全栈小狐狸的逆袭之路: Java学习路线
前端核心:JavaScript
前端核心:jQuery
前端核心:Bootstrap
前端核心:AJAX

你可能感兴趣的:(#,前端:核心技术,前端,ajax,javascript)