1. AJAX

1.1 AJAX 简介

AJAX 全名 Asynchronous Javascript and XML(异步 JavaScript 和 XML)

  • AJAX 不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式。

  • 通过 AJAX 可以在浏览器中向服务器发送异步请求,可以实现 无刷新获取数据。

应用场景:

在这里插入图片描述

1.2 AJAX 优缺点

可以无需刷新页面而与服务器端进行通信。

允许你根据用户事件(鼠标事件、键盘事件、表单事件…)来更新部分页面内容。


没有浏览历史,不能回退。

存在跨域问题

SEO 不友好,AJAX的内容是动态创建到页面当中去,不好爬取代码。

1.3 AJAX 前后端准备

使用 nodejs 作为服务端,与 html 页面交互

在这里插入图片描述

GET.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>AJAX GET 请求</title>
    <style>
        #result{
            width: 200px;
            height: 100px;
            border: solid 1px red;
        }
    </style>
</head>
<body>
    <button>点击发送请求</button>
    <div id="result"></div>
</body>
</html>

server.js

const express = require("express");

const app = express();

// 路由规则
app.get("/server", (request, response) => {
  // 设置响应头,允许跨域
  response.setHeader("Access-Controll-Allow-Origin", "*");
  // 设置响应体
  response.send("Hello AJAX");
});

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

1.4 AJAX 请求基本操作

点击按钮向服务端发送 AJAX 请求,响应结果到 div 中

发送 AJAX 请求操作:

<script>
    const btn = document.getElementsByTagName("button")[0];
btn.onclick = function () {
    // 1.创建对象
    const xhr = new XMLHttpRequest();
    // 2.初始化, 设置请求方法和url
    xhr.open("GET", "http://127.0.0.1:8000/server");
    // 3.发送
    xhr.send();
    // 4.事件绑定 处理服务端返回的结果
    // readyState: 0-未初始化 1-open方法调用完毕 2-send方法调用完毕 3-服务端返回了部分结果 4-服务端返回了所有结果
    xhr.onreadystatechange = function () {
        // 判断服务端是否返回了所有结果
        if (xhr.readyState === 4) {
            // 判断是否响应成功 2xx
            if (xhr.status >= 200 && xhr.status < 300) {
                console.log(xhr.status); // 状态码
                console.log(xhr.statusText); // 状态字符串
                console.log(xhr.getAllResponseHeaders()); // 所有响应头
                console.log(xhr.response); // 响应体
            } else {
            }
        }
    };
};
</script>

AJAX 请求成功

返回响应结果到页面中

<script>
    const btn = document.getElementsByTagName("button")[0];
const result = document.getElementById("result");
btn.onclick = function () {
    // 1.创建对象
    const xhr = new XMLHttpRequest();
    // 2.初始化, 设置请求方法和url
    xhr.open("GET", "http://127.0.0.1:8000/server");
    // 3.发送
    xhr.send();
    // 4.事件绑定 处理服务端返回的结果
    // readyState: 0-未初始化 1-open方法调用完毕 2-send方法调用完毕 3-服务端返回了部分结果 4-服务端返回了所有结果
    xhr.onreadystatechange = function () {
        // 判断服务端是否返回了所有结果
        if (xhr.readyState === 4) {
            // 判断是否响应成功 2xx
            if (xhr.status >= 200 && xhr.status < 300) {
                result.innerHTML = xhr.response;
            } else {
            }
        }
    };
};
</script>

在这里插入图片描述

1.5 AJAX 发送 POST 请求

鼠标移入 div 时向服务端发请求,然后把响应体结果放入 div 中呈现

AJAX 发送 POST 请求

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 (xhr.readyState === 4) {
            if (xhr.status >= 200 && xhr.status < 300) {
                result.innerHTML = xhr.response;
            }
        }
    };
});

nodejs 添加对应的路由规则

app.post("/server", (request, response) => {
    // 设置响应头,允许跨域
    response.setHeader("Access-Control-Allow-Origin", "*");
    // 设置响应体
    response.send("Hello AJAX POST");
});

在这里插入图片描述

附带请求参数

xhr.send("a=199&b=1");

1.6 设置请求头

在这里插入图片描述

由于使用了自定义头,浏览器安全机制会阻止发送请求

在这里插入图片描述

在 nodejs 中设置放行所有头信息

放行之后仍然不行,因为还会发送一个 OPTIONS 的请求做一个头信息校验,这时没有匹配的路由规则所以无法成功。

在这里插入图片描述

路由规则设置为 all 可以接受任意类型的请求即可

20241111114815583

1.7 响应 JSON 数据

nodejs:

app.all("/json-server", (request, response) => {
    // 设置响应头,允许跨域
    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Access-Control-Allow-Headers", "*");

    const data = {
        name: "Fetters"
    };

    let str = JSON.stringify(data)

    // 设置响应体
    response.send(str);
  });	

1️⃣ 手动数据转换

const result = document.getElementById("result");
result.addEventListener("mouseover", function () {
    const xhr = new XMLHttpRequest();
    xhr.open("POST", "http://127.0.0.1:8000/json-server");
    xhr.send();
    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
            if (xhr.status >= 200 && xhr.status < 300) {
                // 手动对数据转换
                let data = JSON.parse(xhr.response);
                result.innerHTML = data;
            }
        }
    };
});

2️⃣ 设置响应体类型自动转换

const result = document.getElementById("result");
result.addEventListener("mouseover", function () {
    const xhr = new XMLHttpRequest();

    // 设置响应体数据的类型
    xhr.responseType = "json";

    xhr.open("POST", "http://127.0.0.1:8000/json-server");
    xhr.send();
    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
            if (xhr.status >= 200 && xhr.status < 300) {
                result.innerHTML = xhr.response.name;
            }
        }
    };
});

在这里插入图片描述

1.8 AJAX 请求超时与网络异常处理

nodejs:

app.get("/delay", (request, response) => {
  response.setHeader("Access-Control-Allow-Origin", "*");
  setTimeout(() => {
    response.send("延时响应");
  }, 3000);
});

html:

<body>
    <button>点击发送请求</button>
    <div id="result"></div>
    <script>
        const btn = document.getElementsByTagName("button")[0];
        const result = document.getElementById("result");

        btn.addEventListener("click", function () {
            const xhr = new XMLHttpRequest();

            // 超时设置, 2s
            xhr.timeout = 2000;
            // 超时回调
            xhr.ontimeout = function () {
                alert("网络异常,请稍后重试!");
            };
            // 网络异常回调
            xhr.onerror = function () {
                alert("您的网络似乎出现了一些问题!")
            }

            xhr.open("GET", "http://127.0.0.1:8000/delay");
            xhr.send();
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4) {
                    if (xhr.status >= 200 && xhr.status < 300) {
                        result.innerHTML = xhr.response;
                    }
                }
            };
        });
    </script>
</body>

请求超时:

网络异常:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在这里插入图片描述

1.9 取消请求

html:

<body>
    <button>点击发送请求</button>
    <button>点击取消请求</button>
    <script>
        const btns = document.querySelectorAll("button");
        let xhr = null;

        btns[0].onclick = function () {
            xhr = new XMLHttpRequest();
            xhr.open("GET", "http://127.0.0.1:8000/delay");
            xhr.send();
        };

        // abort
        btns[1].onclick = function () {
            xhr.abort();
        };
    </script>
</body>

20241111152758070

1.10 Fetch 发送 Ajax 请求

btn.onclick = function () {
    fetch("http://127.0.0.1:8000/fetch-server?vip=10", {
        // 请求方法
        method: "POST",
        // 请求头
        headers: {
            name: "Fetters",
        },
        // 请求体
        body: "username=admin&password=admin",
    }).then(response => {
        return response.text();
    }).then(data => {
        console.log(data);
    });
};

2. jQuery-Ajax

2.1 jQuery 发送 Ajax 请求(GET和POST)

// GET
$('button').eq(0).click(function() {
    $.get('http://127.0.0.1:8000/jquery-server', {a:100, b:200}, function(data) {
        console.log(data);
    }, 'json');
});


// POST
$('button').eq(0).click(function() {
    $.post('http://127.0.0.1:8000/jquery-server', {a:100, b:200}, function(data) {
        console.log(data);
    });
});

2.2 jQuery 通用方法发送 Ajax 请求

$('button').eq(2).click(function() {
    $.ajax({
        // url
        url: 'http://127.0.0.1:8000/jquery-server',
        // 参数
        data: {a: 100, b:200},
        // 请求类型
        type: 'GET',
        // 响应体结果
        dataType: 'json',
        // 成功的回调
        success: function(data) {
            console.log(data);
        },
        // 超时时间
        timeout: 2000,
        // 失败的回调
        error: function() {
            console.log('error!');
        },
        // 头信息
        headers: {
            c: 300,
            d: 400
        }
    });
});

3. Axios-Ajax

在这里插入图片描述

3.1 Axios 发送 Ajax 请求(GET和POST)

const btns = document.querySelectorAll("button");

// 配置 baseURL
axios.defaults.baseURL = "http://127.0.0.1:8000";

btns[0].onclick = function () {
    // GET
    axios.get("/axios-server", {
        // url 参数
        params: {
            id: 100,
            vip: 7,
        },
        // 请求头参数
        headers: {
            name: "Fetters",
            age: 23,
        },
    }).then(value => console.log(value));
};

btns[1].onclick = function () {
    // POST
    axios.post("/axios-server",
        // 请求体
        {
            username: "admin",
            password: "admin",
        },
        {
            // url 参数
            params: {
                id: 100,
                vip: 7,
            },
            // 请求头参数
            headers: {
                name: "Fetters",
                age: 23,
            },
        }
    ).then(value => console.log(value));
};

3.2 Axios 函数发送 Ajax 请求

btns[2].onclick = function () {
    axios({
        // 请求方法
        method: "POST",
        // url
        url: "/axios-server",
        // url 参数
        params: {
            vip: 10,
            level: 20,
        },
        // 头信息
        headers: {
            a: 100,
            b: 200,
        },
        // 请求体参数
        data: {
            username: "admin",
            password: "admin",
        },
    }).then(response => {
        console.log(response);
    });
};

4. 跨域

4.1 同源策略

同源策略(Same-Origin Policy)最早由 Netscape 公司提出,是浏览器的一种安全策略。

同源:协议、域名、端口号 必须完全相同

违背同源策略就是跨域

4.2 如何解决跨域

4.2.1 JSONP

  1. JSONP是什么

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

  2. JSONP 怎么工作的?

    在网页有一些标签天生具有跨域能力,比如:img, link, iframe, script。

    JSONP就是利用 script 标签的跨域能力来发送请求的。

  3. JSONP的使用

    • 获取客户端发送过来的回调函数的名字

    • 得到要通过JSONP形式发送给客户端的数据

    • 根据前两步得到的数据,拼接出一一个函数调用的字符串

    • 把上一步拼接得到的字符串,响应给客户端的``标签进行解析执行

    ️ node服务器端代码

    const express = require('express')
    const app = express()
    const port = 3000
    
    //路由配置
    app.get("/user",(req,res)=>{
        //1.获取客户端发送过来的回调函数的名字
        let fnName = req.query.callback;
        //2.得到要通过JSONP形式发送给客户端的数据
        const data = {name:'tom'}
        //3.根据前两步得到的数据,拼接出个函数调用的字符串
        let result = `${fnName}({name:"tom"})`
        //4.把上步拼接得到的字符串,响应给客户端的<script> 标签进行解析执行
        res.send(result);
    })
    
    app.listen(port, () => {
        console.log(`Example app listening on port ${port}`)
    })
    
    

    ️ 前端代码

    <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>JSONP简单实现</title>
    </head>
    <body>
        <button id="btn">点击发送请求</button>
        <script>
            function getJsonpData(data) {
                console.log("获取数据成功")
                console.log(data) //{name:'tom'}
            }
            var btn = document.getElementById("btn");
            btn.onclick = function () {
                //创建script标签
                var script = document.createElement("script");
                script.src = 'http://localhost:3000/user?callback=getJsonpData';
                document.body.appendChild(script);
                script.onload = function () {
                    document.body.removeChild(script)
                }
            }
        </script>
    </body>
    </html>
    

4.2.2 CORS

推荐文章

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

  2. CORS怎么工作的?

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

  3. CORS 的使用

    // 设置响应头,允许跨域
    response.setHeader("Access-Control-Allow-Origin", "*");
    

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部