Ajax笔记

简介

无刷新情况下向后端发送请求

XML

<student>
    <name></name>
    <age></age>
    <gender></gender>
</student>

标签自定义
数据交互格式为XML,已经被JSON取代

特点

优点

  • 无需刷新与服务器进行通信
  • 根据用户事件更新部分内容

缺点

  • 没有浏览历史,不能回退
  • 存在跨域问题
  • SEO不友好

HTTP协议

重点格式与参数

请求报文

行:请求类型(get、post等)、url路径、http协议版本
头:
    Host:
    Cookie:
    Content-type:
    User-agent:
空行
请求体:
    若为get,为空;
    若为post可以不为空

响应报文

行:http协议版本、响应状态码(400,403,401,500,200),响应状态字符串
头:
    Content-type:
    Content-length:
    Content-encoding:
空行
请求体:
    <html>
        <head>
        </head>
        <body>

        </body>
    </html>

应用Node.js和express编写简单server.js

  1. express.js
// 1. 引入express
const express = require('express');

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

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

// 4. 监听端口启动服务
app.listen(8000, ()=>{
    console.log("服务已经启动,8000端口监听中……")
})
  1. server.js
// 1. 引入express
const express = require('express')

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

// 3. 创建路由规则
// 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.setHeader('Access-Control-Allow-Headers', '*')
    response.send('Hello Ajax POST')
})

app.all('/server', (request, response)=>{
    // 设置响应
    response.setHeader('Access-Control-Allow-Origin', '*')
    response.setHeader('Access-Control-Allow-Headers', '*')
    response.send('Hello Ajax POST')
})

app.all('/json-server', (request, response)=>{
    // 设置响应
    response.setHeader('Access-Control-Allow-Origin', '*')
    response.setHeader('Access-Control-Allow-Headers', '*')
    const date = {
        name: 'zdp'
    }
    let str = JSON.stringify(date)
    response.send(str)
})
// 4-ie缓存问题:ie浏览器对ajax的返回作缓存,如果再次请求,只会返回缓存,对时效性较高的业务有影响
app.all('/ie', (request, response)=>{
    // 设置响应
    response.setHeader('Access-Control-Allow-Origin', '*')
    response.send('Hello Ajax IE 2')
})

app.all('/timeout', (request, response)=>{
    // 设置响应
    response.setHeader('Access-Control-Allow-Origin', '*')
    setTimeout(()=>{
        response.send('Hello Ajax Timeout')
    }, 3000)
    
})

// jquery服务
app.all('/jquery', (request, response)=>{
    // 设置响应
    response.setHeader('Access-Control-Allow-Origin', '*')
    response.setHeader('Access-Control-Allow-Headers', '*')
    const date = {name:'zdp'}
    response.send(JSON.stringify(date))
})

app.all('/axios', (request, response)=>{
    // 设置响应
    response.setHeader('Access-Control-Allow-Origin', '*')
    response.setHeader('Access-Control-Allow-Headers', '*')
    const date = {name:'zdp'}
    response.send(JSON.stringify(date))
})

app.all('/fetch', (request, response)=>{
    // 设置响应
    response.setHeader('Access-Control-Allow-Origin', '*')
    response.setHeader('Access-Control-Allow-Headers', '*')
    const date = {name:'zdp'}
    response.send(JSON.stringify(date))
})

app.all('/jsonp', (request, response)=>{
    // 设置响应
    response.setHeader('Access-Control-Allow-Origin', '*')
    response.setHeader('Access-Control-Allow-Headers', '*')
    const data = {
        name: 'zdp'
    }
    let str = JSON.stringify(data)
    response.end(`handle(${str})`)
    // response.send('console.log("hello")')
})

app.all('/check-username', (request, response)=>{
    response.setHeader('Access-Control-Allow-Origin', '*')
    response.setHeader('Access-Control-Allow-Headers', '*')
    const data = {
        exist:1,
        msg: '用户名已经存在'
    }
    let str = JSON.stringify(data)
    response.end(`handle(${str})`)
})

app.all('/jquery-jsonp', (request, response)=>{
    const data = {
        name: 'zdp',
        city: ['北京', '上海',]
    }
    let cb = request.query.callback

    let str = JSON.stringify(data)
    response.end(`${cb}(${str})`)
})

app.all('/cors', (request, response)=>{
    // 设置跨域
    response.setHeader('Access-Control-Allow-Origin', '*')
    response.setHeader('Access-Control-Allow-Headers', '*')
    response.setHeader('Access-Control-Allow-Method', '*')
    response.send("hello")
})


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

原生Ajax

1-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>
    <style>
        #result {
            width: 200px;
            height: 100px;
            border: solid 1px;
        }
    </style>
</head>
<body>
    <button>点击发送请求</button>
    <div id="result"></div>
    <script>
        const btn = document.getElementsByTagName('button')[0]
        const result = document.getElementById('result')
        btn.onclick = function () {
            const xhr = new XMLHttpRequest()
            // ?后设置参数
            xhr.open('GET', 'http://127.0.0.1:8000/server?a=100&b=200&c=300');
            xhr.send();
            // readstate xhr对象属性
            //  0 未初始化
            // 1 open调用完毕
            // 2 send调用完毕
            // 3 服务端返回部分结果
            // 4 服务端所有部分结果
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4) {
                    if (xhr.status >= 200 && xhr.status < 300) {   // 2开头都是成功的
                        // 处理结果
                        console.log(xhr.status)
                        console.log(xhr.statusText)
                        console.log(xhr.getAllResponseHeaders())
                        console.log(xhr.response)
                        result.innerHTML = xhr.response
                    }
                }
            }
        }
    </script>
</body>
</html>

2-post.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>
    <style>
        #result {
            width: 200px;
            height: 100px;
            border: solid 1px #903;
        }
    </style>
</head>
<body>
    <div id="result"></div>
    <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.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
            // 自定义请求头,在server.js加一行
            xhr.setRequestHeader('name', 'zdp')
            xhr.send('a=100&b=200&c=300')   // 设置参数
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4) {
                    if (xhr.status >= 200 && xhr.status < 300) {
                        result.innerHTML = xhr.response
                    }
                }
            }
        })
    </script>
</body>
</html>

3-json.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>
    <style>
        #result {
            width: 200px;
            height: 100px;
            border: solid 1px #903;
        }
    </style>
</head>
<body>
    <div id="result"></div>
    <script>
        const result = document.getElementById('result')
        window.addEventListener('keyup', function() {
            console.log("键盘")
            const xhr = new XMLHttpRequest()
            // 设置响应体数据类型
            xhr.responseType = 'json'
            xhr.open('GET', 'http://127.0.0.1:8000/json-server')
            // 设置请求头
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
            // 自定义请求头,在server.js加一行
            xhr.setRequestHeader('name', 'zdp')
            xhr.send('a=100&b=200&c=300')   // 设置参数
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4) {
                    if (xhr.status >= 200 && xhr.status < 300) {
                        // result.innerHTML = xhr.response
                        // 手动转换
                        // let date = JSON.parse(xhr.response)
                        // result.innerHTML = date.name
                        // 自动转换,需要设置response格式
                        result.innerHTML = xhr.response.name
                    }
                }
            }
        })
    </script>
</body>
</html>

4-ie缓存问题

<!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>
    <style>
        #result {
            width: 200px;
            height: 100px;
            border: solid 1px;
        }
    </style>
</head>
<body>
    <button>点击发送请求</button>
    <div id="result"></div>
    <script>
        const btn = document.getElementsByTagName('button')[0]
        const result = document.querySelector('#result')
        btn.addEventListener('click', function () {
            const xhr = new XMLHttpRequest()
            // ?增加参数,使ie浏览器认为不一样
            xhr.open('GET', 'http://127.0.0.1:8000/ie?t='+Date.now());
            xhr.send();
            // readstate xhr对象属性
            //  0 未初始化
            // 1 open调用完毕
            // 2 send调用完毕
            // 3 服务端返回部分结果
            // 4 服务端所有部分结果
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4) {
                    if (xhr.status >= 200 && xhr.status < 300) {   // 2开头都是成功的
                        // 处理结果
                        result.innerHTML = xhr.response
                    }
                }
            }
        })
    </script>
</body>
</html>

5-超时处理与网络异常

<!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>
    <style>
        #result {
            width: 200px;
            height: 100px;
            border: solid 1px;
        }
    </style>
</head>
<body>
    <button>点击发送请求</button>
    <div id="result"></div>
    <script>
        const btn = document.getElementsByTagName('button')[0]
        const result = document.querySelector('#result')
        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/timeout');
            xhr.send();
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4) {
                    if (xhr.status >= 200 && xhr.status < 300) {   // 2开头都是成功的
                        // 处理结果
                        result.innerHTML = xhr.response
                    }
                }
            }
        })
    </script>
</body>
</html>

6-取消请求.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>send</button>
    <button>cancel</button>
    <script>
        const btns = document.querySelectorAll('button')
        let x = null
        btns[0].addEventListener('click', function() {
            x = new XMLHttpRequest()
            x.open('GET', 'http://127.0.0.1:8000/timeout')
            x.send()
        })
        btns[1].addEventListener('click', function () {
            x.abort()
        })
    </script>
</body>
</html>

7-重复请求处理.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>send</button>
    <script>
        const btns = document.querySelectorAll('button')
        let x = null
        let isSending = false;
        btns[0].addEventListener('click', function() {
            // 如果正在发送,则取消该请求,创建一个新请求
            if (isSending) x.abort()
            x = new XMLHttpRequest()
            isSending = true
            x.open('GET', 'http://127.0.0.1:8000/timeout')
            x.send()
            x.onreadystatechange = function(){
                if (x.readyState === 4) {
                    isSending = false
                }
            }
        })
    </script>
</body>
</html>

fetch.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>Ajax请求</button>
    <script>
        const btn = document.querySelector('button')
        btn.onclick = function () {
            fetch('http://127.0.0.1:8000/fetch?vip=10', {
                method: 'POST',
                headers: {
                    a: 100
                },
                body: 'username=admin&password=admin'
            }).then(response => {
                console.log(response)
                // return response.text();
                return response.json();
            }).then(response => {
                console.log(response)
            })
        }
    </script>
</body>
</html>

jquery-ajax

<!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>
    <link crossorigin="anonymous" rel="stylesheet" href="./css/bootstrap-theme.min.css">
    <script crossorigin="anonymous" src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
</head>
<body>
    <div class="container">
        <h2 class="page-header">
            jQuery发送Ajax请求
        </h2>
        <button class="btn btn-primary">GET</button>
        <button class="btn btn-danger">POST
        </button>
        <button class="btn btn-info">通用型方法Ajax</button>
    </div>
    <script>
        $('button').eq(0).click(function(){
            $.get('http://127.0.0.1:8000/jquery', {a:100, b:200}, function (date){
                console.log(date.name)
            }, 'json')
        })
        $('button').eq(1).click(function(){
            $.post('http://127.0.0.1:8000/jquery', {a:100, b:200}, function (date){
                console.log(date)
            })
        })
        $('button').eq(2).click(function(){
            $.ajax({
                // url:'http://127.0.0.1:8000/jquery',
                url:'http://127.0.0.1:8000/timeout',
                date:{a:100, b:200},
                type: 'GET',
                //响应体结构
                dataType:'json',
                success: function(date) {
                    console.log(date)
                },
                timeout: 2000,
                error: function(){
                    console.log('出错!')
                },
                //自定义头信息
                headers: {
                    c:300,
                    d:400
                }
            })
        })
    </script>
</body>
</html>

axios

<!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>
    <script crossorigin="anonymous" src="https://cdn.bootcdn.net/ajax/libs/axios/1.3.3/axios.min.js"></script>
</head>
<body>
    <button>GET</button>
    <button>POST</button>
    <button>Ajax</button>
    <script>
        const btns = document.querySelectorAll('button')
        axios.defaults.baseURL = 'http://127.0.0.1:8000/'
        btns[0].onclick = function () {
            // get
            axios.get('/axios', {
                params: {
                    id:100,
                    vip:7
                },
                headers: {
                    name: 'zdp'
                }
            }).then(value => {
                console.log(value)
            })
        }
        btns[1].onclick = function () {
            // post
            axios.post('/axios', {
                    username: 'admin'
                }, {
                params: {
                    id:100,
                    vip:7
                },
                headers: {
                    name: 'zdp'
                }
            })
        }
        btns[2].onclick = function () {
            axios({
                method: 'POST',
                url: '/axios',
                params: {
                    vip: 10
                },
                headers: {
                    a: 100
                },
                data: {
                    username:'zdp'
                }
            }).then(response => {
                console.log(response)
                console.log(response.status)
                console.log(response.headers)
                console.log(response.data)
            })
        }
    </script>
</body>
</html>

跨域问题

同源

协议、域名、端口号必须完全相同
Ajax遵循同源策略

  1. index.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>
    <h1>zdp</h1>
    <button>获取数据</button>
    <script>
        const btn = document.querySelector('button')
        btn.onclick = function () {
            const x = new XMLHttpRequest();
            x.open("GET", '/data')
            x.send()
            x.onreadystatechange = function () {
                if (x.readyState === 4) {
                    if (x.status >= 200 && x.status < 300) {
                        console.log(x.response)
                    }
                }
            }
        }
    </script>
</body>
</html>
  1. server.js
const express = require('express')
const app = express()

app.get('/home', (request, response)=>{
    response.sendFile(__dirname + '/index.html')

})

app.get('/data', (request, response)=>{
    response.send('Hello')
})

app.listen(9000, ()=>{
    console.log("服务已经启动...")
})

跨域

违背同源策略就是跨域

jsonp

script标签本身是跨域的

script里src写上跨域js代码,返回函数调用js语句

  1. jsonp.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>
    <style>
        #result {
            width: 200px;
            height: 100px;
            border: solid 1px;
        }
    </style>
</head>
<body>
    <div id="result"></div>
    <script>
        function handle(data) {
            const result = document.querySelector('#result')
            result.innerHTML = data.name
        }
    </script>
    <script src="http://127.0.0.1:8000/jsonp"></script>
</body>
</html>
  1. 创建script标签
<!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>
    用户名:<input type="text" id="username">
    <p></p>
    <script>
        const input = document.querySelector('input')
        const p = document.querySelector('p')
        function handle(data) {
            input.style.border = "solid 1px #f00"
            p.innerHTML = data.msg
        }
        input.onblur = function () {
            let username = this.value
            const script = document.createElement('script')
            script.src = 'http://127.0.0.1:8000/check-username'
            document.body.appendChild(script)
        }
    </script>
</body>
</html>
  1. jquery.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>
    <style>
        #result {
            width: 200px;
            height: 100px;
            border: solid 1px #089;
        }
    </style>
    <script crossorigin="anonymous" src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
</head>
<body>
    <button>发送</button>
    <div id="result"></div>
    <script>
        $('button').eq(0).click(function () {
            // callback必须填写
            $.getJSON('http://127.0.0.1:8000/jquery-jsonp?callback=?', function (data) {
                console.log(data)
                $('#result').html(`
                    名称:${data.name}<br>
                    校区:${data.city}
                `)
            })
        })
    </script>
</body>
</html>

CORS

官方跨域解决方案
支持get,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>Document</title>
    <style>
        #result {
            width: 200px;
            height: 100px;
            border: solid 1px;
        }
    </style>
</head>
<body>
    <button>send</button>
    <div id="result"></div>
    <script>
        const btn = document.querySelector('button')
        const result = document.querySelector('#result')
        btn.onclick = function () {
            const x = new XMLHttpRequest()
            x.open('GET', 'http://127.0.0.1:8000/cors')
            x.send()
            x.onreadystatechange = function(){
                if (x.readyState === 4) {
                    if (x.status >= 200 && x.status < 300) {
                        console.log(x.response)
                        result.innerHTML = x.response
                    }
                }
            }
        }
    </script>
</body>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值