AJAX,无需刷新获取数据

AJAX

Asynchronous JavaScript And XML,译为 异步的 JS 和 XML

通过AJAX可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据

XML (可扩展标记语言)

用来存储数据。但其基本被JSON取代

AJAX的特点

优点:

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

  2. 允许根据用户事件来更新部分页面内容。

缺点:

  1. 没有浏览历史,不能回退

  2. 存在跨域问题 (同源)

  3. SEO不友好

HTTP协议

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

请求报文和响应报文

二者格式都是:

空行

按步骤引用express框架

get

html:

<!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>
    <button>点击发送请求</button>
    <div id="res"></div>
    <script>
        const btn = document.getElementsByTagName('button')[0];
        //绑定事件
        btn.onclick = function(){
            //1.创建对象
            const xhr = new XMLHttpRequest();
            //2.初始化 设置请求方法和 url
            xhr.open('GET','http://localhost:8000/server?a=100&b=200');
            //3.发送
            xhr.send();
            //4.事件绑定 处理服务端返回的结果
            // on 当...时候
            // readystate 是 xhr 对象中的属性,表示状态 0 1 2 3 4
            // change 改变
            xhr.onreadystatechange = function(){
                //判断(服务端返回了所有的结果)
                if(xhr.readyState === 4)
                {
                    //判断响应状态码 200 404 403 401 500
                    //2xx都是表示成功
                    if(xhr.status >=200 && xhr.status < 300)
                    {
                        //处理结果  行 头 空行 体
                        //1.响应行
                        console.log(xhr.status);//状态码
                        console.log(xhr.statusText);//状态字符串
                        console.log(xhr.getAllResponseHeaders());//所有响应头
                        console.log(xhr.response);//响应体
                    }else{
                        
                    }
                }
            }
        }
    </script>
    
</body>
</html>

js:

// 引入express 
const express = require('express');
//创建应用对象
const app = express();
//创建路由规则
//request   是对请求报文的封装
//response  是对响应报文的封装
app.get('/server', (request, response) => {
    //设置响应头    设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    //设置响应体
    response.send('HELLO AJAX');
});
app.listen(8000, () => {
    console.log("服务器已经启动,8000 端口监听中....");
}); 

post

<!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 POST 请求</title>
    <style>
        #res{
            width: 100px;
            height: 50px;
            background-color: gray;
            border-radius: 10px;
        }
    </style>
</head>
<body>
    <div id="res"></div>
​
    <script>
        //获取元素对象
        const res = document.getElementById('res');
        //绑定事件
        res.onmouseover = function(){
            //1.创建对象
            const xhr = new XMLHttpRequest();
            //2.初始化设置类型与URL
            xhr.open('POST','http://127.0.0.1:8000/server');
            //3.发送
            xhr.send();
            //4.事件绑定
            xhr.onreadystatechange = function(){
                //判断
                if(xhr.readyState === 4)
                {
                    //处理服务端返回的结果
                    res.innerHTML = xhr.response;
                }
            }
        }
    </script>
</body>
</html>
// 引入express 
const express = require('express');
//创建应用对象
const app = express();
//创建路由规则
//request   是对请求报文的封装
//response  是对响应报文的封装
app.get('/server', (request, response) => {
    //设置响应头    设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    //设置响应体
    response.send('HELLO AJAX');
});
app.post('/server', (request, response) => {
    //设置响应头    设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    //设置响应体
    response.send('HELLO AJAX POST');
});
app.listen(8000, () => {
    console.log("服务器已经启动,8000 端口监听中....");
}); 

设置请求体

请求体在send()方法中设置

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

设置请求头信息

setRequestHeader()

在open和send方法中间设置请求头

xhr.open('POST','http://127.0.0.1:8000/server');
//设置请求头
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
xhr.send('a=100&b=200&c=300'); 

服务端响应json数据

接收服务端的数据只能接收字符串

所以当服务端要传字符串时,需要将对象进行字符串转化

let str = JSON.stringify(data);

js:

// 引入express 
const express = require('express');
//创建应用对象
const app = express();
app.all('/json-server', (request, response) => {
    //设置响应头    设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    //响应一个数据
    const data = {
        name:'xiaotao'
    }
    //对对象进行字符串转换
    let str = JSON.stringify(data);
    // 设置响应体
    response.send(str);
});
app.listen(8000, () => {
    console.log("服务器已经启动,8000 端口监听中....");
}); 

接收服务端数据后将数据转换为对象

两种方式:

  1. 手动对数据进行转化

    let data = JSON.parse(xhr.response);
    console.log(data);
  2. 自动转换

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

    console.log(xhr.response);
    res.innerHTML = xhr.response.name;

整体代码:

    <script>
        const res = document.getElementById('res');
        // 绑定键盘按下事件
        window.onkeydown = function(){
            //发送请求
            const xhr = new XMLHttpRequest();
            //设置响应体数据的类型
            xhr.responseType = 'json';
            //初始化
            xhr.open('GET','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);
                        // console.log(data);
​
                        //自动转换
                        console.log(xhr.response);
                        res.innerHTML = xhr.response.name;
                    }
                }
            }
        }
    </script>

请求超时和网络异常处理

ontimeout():请求超时事件

onerror():无网络事件

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

完整script代码:

    <script>
        const btn = document.getElementsByTagName('button')         [0];
        const res = document.querySelector('#res');
​
        btn.addEventListener('click',function(){
            const xhr = new XMLHttpRequest();
​
            //超时设置
            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)
                    {
                        res.innerHTML = xhr.response;
                    }
                }
            }
        });
    </script>

取消请求

当请求还没有到达的时候取消请求,使用abort方法

x.abort();

完整代码:

<!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>
    <button>点击发送</button>
    <button>点击取消</button>
    <script>
        const btns = document.getElementsByTagName('button');
        let x = null;
​
        btns[0].onclick = function(){
            x = new XMLHttpRequest();
            x.open('GET','http://127.0.0.1:8000/delay');
            x.send();
        }
​
        btns[1].onclick = function(){
            x.abort();
        }
    </script>
</body>
</html>
// 引入express 
const { response } = require('express');
const express = require('express');
//创建应用对象
const app = express();
//延时响应
app.get('/delay', (request, response) => {
    response.setHeader('Access-Control-Allow-Origin', '*')
    setTimeout(() => {
        response.send('延时响应');
    }, 2000);
});
//监听端口启动服务
app.listen(8000, () => {
    console.log("服务器已经启动,8000 端口监听中....");
}); 

重复请求发送问题

为了提升效率,避免用户重复发送相同的请求,当用户按下请求时,判断是否已有请求,如果有,取消上一个请求,创建一个新的请求。

const btns = document.getElementsByTagName('button');
let x = null;
//标识变量
let isSending = false;
​
btns[0].onclick = function(){
    //判断标识变量
    if(isSending)
    {
        x.abort();//如果正在发送,则取消请求,创建一个新的请求
    }
    x = new XMLHttpRequest();
    //需修改标识变量的值
    isSending = true;
    x.open('GET','http://127.0.0.1:8000/delay');
    x.send();
    x.onreadystatechange = function(){
        if(x.readyState === 4)
        {
            //修改标识变量
            isSending = false;
        }
    }
}

同源策略

是浏览器的一种安全策略

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

违背同源策略就是跨域

跨域的解决方案

  1. JSONP

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

JSONP是借助script来实现跨域的

原生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>案例</title>
</head>
<body>
    用户名:<input type="text" id="username">
    <p></p>
    <script>
        const input = document.querySelector('input');
        const p = document.querySelector('p');
​
        //声明handle函数
        function handle(data){
            input.style.border = "solid 1px #f00";
            //修改p标签的提示文本
            p.innerHTML = data.msg;
        }
​
        //绑定事件
        input.onblur = function(){
            //获取用户输入的值
            let username = this.value;
            //向服务器端发送请求,检测用户名是否存在
            //1.创建一个script标签
            const script = document.creatElement('script');
            //2.设置标签的 src 属性
            script.src = 'http://127.0.0.1:8000/check-username'
            //3.将script插入到文档中
            document.body.appendChild(script);
        }
    </script>
</body>
</html>

CORS

跨域资源共享,是官方的解决跨域的方法

一般来说是设置响应头:

response.setHeader('Access-Control-Allow-Origin', '*');

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值