AJAX请求-新
ajax 优点
- 无需刷新页面,就可以与服务端进行通信
- 允许根据用户事件来更新部分页面内容
ajax 缺点
- 没有浏览历史,不能回退
- 存在跨域问题
- SEO不友好 (对搜索引擎不太友好)
HTTP请求报文
请求行 : GET / url路径(或者字符串) HTTP/1.1
请求头 : HOST: www.kkdaly.top
空行
请求报文主体 username=admin&password=123.com
// 以上是完整的http协议报文
HTTP响应报文
响应行 HTTP/1.1 200 ok
响应头 Content-Type : text/html;charset=utf-8
空行
响应报文主体 <html></html> //返回html主体
通过按钮发送GET请求到服务器
- 服务端代码
// 引入 express const express = require('express'); // 创建应用对象 const app = express(); // 创建路由规则 // request是对请求报文的封装 // response是对响应报文的封装 app.get('/server', (request, response) => { // 设置响应头 设置允许跨域 response.setHeader('Access-Control-Allow-Origin', '*'); // 设置响应 // 服务端返回的数据 response.send('hello world'); }); app.listen(4000, () => { console.log('服务已启动,4000端口监听'); });
- 前端代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=S, initial-scale=1.0"> <title>Document</title> </head> <style> div { width: 200px; height: 200px; border: solid 1px pink; } </style> <body> <button>发送请求</button> <div></div> </body> <script> // 获取元素 let btn = document.querySelector('button'); let div = document.querySelector('div'); // 绑定事件 通过点击按钮发送ajax请求 btn.addEventListener('click', function() { // ajax请求发送流程 // 1. 创建对象 const xhr = new XMLHttpRequest(); // 2.初始化 xhr.open('GET', 'http://127.0.0.1:4000/server'); // 3.发送 xhr.send(); // 4. 事件绑定 readystate 是xhr对象中的属性,表示当前状态 0 1 2 3 4 // 0 是最开始的值 // 1 表示open方法调用完毕 // 2 表示 send()方法调用完毕 // 3 表示服务端正在响应中,没有完全返回所有数据 // 4 表示服务端返回了所有的结果 xhr.onreadystatechange = function() { // 这里需要判断当前状态是否为4服务端响应了所有数据 // 判断服务端是否返回了所有的结果 if (xhr.readyState === 4) { // 判断响应状态码 if (xhr.status >= 200 && xhr.status <= 300) { // 处理结果 行 头 空行 主体 // 1.响应行 console.log(xhr.status); // 打印状态码 console.log(xhr.statusText); // 打印响应字符串 console.log(xhr.getAllResponseHeaders); // 打印所有响应头 console.log(xhr.response); // 打印响应体 div.innerHTML = xhr.response 将div内的文字变为服务端响应的数据 } } } }) </script> </html>
发送POST请求
- 服务端代码
// 引入 express const express = require('express'); // 创建应用对象 const app = express(); // 创建路由规则 // request是对请求报文的封装 // response是对响应报文的封装 app.post('/server', (request, response) => { // 设置响应头 设置允许跨域 response.setHeader('Access-Control-Allow-Origin', '*'); // 设置响应 // 服务端返回的数据 response.send('hello world post'); }); app.listen(4000, () => { console.log('服务已启动,4000端口监听'); });
- 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> <style> div { width: 200px; height: 200px; border: 1px solid pink; } </style> <body> <div></div> </body> <script> let div = document.querySelector('div'); div.addEventListener('mousemove', function() { // 1.创建对象 const xhr = new XMLHttpRequest(); // 2.初始化 xhr.open('POST', 'http://127.0.0.1:4000/server'); // 3.发送请求 xhr.send(); // 4.事件绑定 判断请求状态 xhr.addEventListener('readystatechange', function() { // 判断 if (xhr.readyState === 4) { if (xhr.status >= 200 && xhr.status <= 300) { // 处理服务端返回的结果 div.innerHTML = xhr.response; } } }) }) </script> </html>
ajax 中 传递参数
- get
// 在初始化时url后面传递参数 // 初始化 xhr.open('GET', 'http://127.0.0.1:4000/server?username="lmk"&password="123.com"'); // 通过 ?参数名=参数值&参数名=参数值 来传递参数
- post
// 在send发送请求是传递参数 //发送请求 xhr.send('a=100&b=200&c=300'); // 里面的格式可以随便写,但是还是尽量用这样写的 或者用json格式
ajax 设置请求头信息
- 通过 setRequestHeader方法设置
// 一般在初始化(open)后面设置 // 1.创建对象 const xhr = new XMLHttpRequest(); // 2.初始化 xhr.open('POST', 'http://127.0.0.1:4000/server'); // 设置请求头 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded') // 设置请求头信息 可以自定义请求头 // 3.发送请求 xhr.send('a=100&b=200&c=300');
ajax 服务端响应json格式的请求
- 服务端
// 引入 express const express = require('express'); // 创建应用对象 const app = express(); // 创建路由规则 // request是对请求报文的封装 // response是对响应报文的封装 app.get('/server', (request, response) => { // 设置响应头 设置允许跨域 response.setHeader('Access-Control-Allow-Origin', '*'); // 定义一个对象,返回给前端 const data = { name: 'lmk' } // 设置响应 // 服务端返回的数据 // 将data对象转换为json字符串返回给前端 response.send(JSON.stringify(data)); }); app.listen(4000, () => { console.log('服务已启动,4000端口监听'); });
- 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> <style> div { width: 200px; height: 200px; border: 1px solid pink; } </style> <body> <div></div> </body> <script> let div = document.querySelector('div'); window.addEventListener('keydown', function() { // 创建对象 const xhr = new XMLHttpRequest(); xhr.responseType = 'json'; // 设置服务器返回的类型为json格式,就不需要自己转换了 // 初始化 xhr.open('GET', 'http://127.0.0.1:4000/server') // 发送 xhr.send(); // 事件绑定 xhr.addEventListener('readystatechange', function() { if (xhr.readyState === 4) { if (xhr.status >= 200 && xhr.status <= 300) { // let data = JSON.parse(xhr.response) // div.innerHTML = data.name // 上面这两个行是手动转换 div.innerHTML = xhr.response.name // 自动转换的 } } }) }) </script> </html>
ajax中ie缓存问题
// 创建对象
const xhr = new XMLHttpRequest();
// 初始化
xhr.open('get', 'http://127.0.0.1:4000/ie?t=' + Date.now()) // 可以在初始化中url后面添加时间戳作为参数,以保证每次请求都是不一样的url,这样就可以避免ie会缓存ajax数据的问题了
// 发送
xhr.send();
// 绑定事件
xhr.addEventListener('readystatechange', function() {
if (xhr.readyState === 4 && xhr.status >= 200 && xhr.status <= 300) {
div.innerHTML = xhr.response
}
ajax 网络请求超时异常处理
- 服务端代码
// 引入 express const express = require('express'); // 创建应用对象 const app = express(); // 创建路由规则 // request是对请求报文的封装 // response是对响应报文的封装 app.get('/server', (request, response) => { response.setHeader('Access-Control-Allow-Origin', '*'); setTimeout(() => { response.send('延迟响应') }, 3000); }) app.listen(4000, () => { console.log('服务已启动,4000端口监听'); });
- 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> <style> div { width: 200px; height: 200px; border: 1px solid pink; } </style> <body> <button>发送请求</button> <div></div> </body> <script> // 获取元素 let btn = document.querySelector('button') let div = document.querySelector('div'); // 绑定点击事件 btn.addEventListener('click', function() { // 创建对象 const xhr = new XMLHttpRequest(); // ajax超时设置 如果超过2秒没有返回就会取消ajax请求 xhr.timeout = 2000; // 返回结果超时的回调 xhr.addEventListener('timeout', function() { div.innerHTML = '返回超时,ajax请求已取消' }) // 网络异常时的回调 xhr.addEventListener('error', function() { div.innerHTML = '你的网络出了问题' }) // 初始化 xhr.open('get', 'http://127.0.0.1:4000/server') // 发送 xhr.send(); // 判断请求结果 xhr.addEventListener('readystatechange', function() { if (xhr.readyState === 4 && xhr.status >= 200 && xhr.status <= 300) { div.innerHTML = xhr.response } }) }) </script> </html>
ajax取消请求
- 通过 abort()方法来手动取消
// 获取元素 let btn = document.querySelector('button') let div = document.querySelector('div'); let btn2 = document.querySelector('input') let xhr = null btn.addEventListener('click', function() { xhr = new XMLHttpRequest(); xhr.open('get', 'http://127.0.0.1:4000/server') xhr.send(); xhr.addEventListener('readystatechange', function() { if (xhr.readyState === 4 && xhr.status >= 200 && xhr.status <= 300) { div.innerHTML = xhr.response } }) }) btn2.addEventListener('click', function() { xhr.abort(); // 通过abort来取消ajax请求 div.innerHTML = 'ajax请求已取消' })
ajax重复发送请求问题
// 如果点击多次,可以把上一次点击的请求取消掉,这样就会只有一个请求了
// 获取元素
let btn = document.querySelector('button')
let div = document.querySelector('div');
let xhr = null
// 节流阀
let flag = false
btn.addEventListener('click', function() {
if (flag) {
xhr.abort(); // 判断flag是否为true(发送请求中)如果为true就取消上一次的请求
}
xhr = new XMLHttpRequest();
flag = true // 修改节流阀
xhr.open('get', 'http://127.0.0.1:4000/server')
xhr.send();
xhr.addEventListener('readystatechange', function() {
if (xhr.readyState === 4) {
div.innerHTML = xhr.response
flag = false; // 请求完成就变为false
}
})
});
jQuery发送ajax方法
get方法
$.get('url',{key:传递的参数},function(data){ // data是服务器响应的数据 // 可以在回调函数中对服务器返回的数据进行一个操作 // 传递的参数是一个对象 },'json') // 这里的最后一个参数json是响应体类型 可以默认将响应数据json字符串转为json格式的数据
post方法
// data是服务器响应的数据 // 可以在回调函数中对服务器返回的数据进行一个操作 // 传递的参数是一个对象 },'json') // 这里的最后一个参数json是响应体类型 可以默认将响应数据json字符串转为json格式的数据
通用方法
$.ajax({ //url url: "http://127.0.0.1:4000/server", // 参数 data: { username: 'lmk', password: '123.com' }, // 请求类型 type: 'GET', // 响应体结果 自动将服务端返回的数据转为这里写的数据 dataType: 'json', // 成功回调 success: function(data) { console.log(data); }, // 设置超时时间 timeout: 3000, // 失败的回调 error: function() { console.log("有错误"); }, // 请求头信息设置 headers: { user: 'lmk' } }) // 成功回调后面的参数都可以省略不写,需要就写上
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> <script src="./jquery.min.js"></script> </head> <body> <button>jQuery-get</button> <button>jQuery-post</button> <button>通用方法</button> </body> <script> $('button').eq(0).click(function() { $.get('http://127.0.0.1:4000/server', { username: 'lmk', password: '123.com' }, function(data) { console.log(data); // data是响应体 }) }) $('button').eq(1).click(function() { $.post('http://127.0.0.1:4000/server', { username: 'lmk', password: '123.com' }, function(data) { console.log(data); // data是响应体 }) }) $('button').eq(2).click(function() { $.ajax({ //url url: "http://127.0.0.1:4000/server", // 参数 data: { username: 'lmk', password: '123.com' }, // 请求类型 type: 'GET', // 响应体结果 自动将服务端返回的数据转为这里写的数据 dataType: 'json', // 成功回调 success: function(data) { console.log(data); }, // 设置超时时间 timeout: 3000, // 失败的回调 error: function() { console.log("有错误"); }, // 请求头信息设置 headers: { user: 'lmk' } }) }) </script> </html>
axios工具库
- 安装
npm install axios // 也可以在页面中直接引用cdn链接 <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
- get请求
axios.get('url',{请求参数}).send(value=>{返回值})
- 示例
axios.get('server', { // 定义url后缀参数 类似 http://127.0.0.1:4000/server?id=100&vip=7 params: { id: 100, vip: 7 }, // 定义请求头信息 如果写自定义请求头需要服务端允许 headers: { name: 'lmk', age: 18 }.then(value => { console.log(value); // 通过 promise接收服务端返回的完整数据 })
- post请求
axios.post('url',{data请求体},{其他参数})
- 示例
axios.post('/server', { firstName: 'lmk', lastName: 'kkdaly' }, { // 设置请求url参数 post也可以请求 可写可不写 params: { id: 1 }, // 设置请求头参数 可以写自定义请求头,前提是必须服务端允许 headers: { width: '123' } }) })
- 通用方式
axios({ // 请求方式 method: 'get', // get或post // url地址 url: '/server', // url后缀参数 params: { id: 100 }, // 请求体 post请求需要添加 get 不需要 // data: { // username: 'kkdaly', // password: '123.com' // }, // 定义请求头 可以自定义,前提是服务端必须允许 headers:{ width: 123 } })
使用 fetch()发送ajax请求
- 发送请求
fetch(url,{一些参数(可选)})
- 实例
fetch('http://127.0.0.1:4000/server?vip=10', { method: 'POST', // 请求方法 headers: { width: 100 // 请求头 }, // body: { // username: 'lmk', // password: '123.com' // } body: 'username=lmk&password=123.com' // 请求体可以这样写也可以像上面写对象 }).then(value => { value.text().then(value => { console.log(value); // }) })
跨域
同源策略
- 由Netscape公司提出,是浏览器的一种安全策略
- 同源 协议 域名 端口号,必须完全相同才可以通讯
解决跨域问题
JSONP
- 是一个非官方的跨域解决方案,只支持get请求
原生jsonp跨域请求
- 服务端代码
// 引入 express const express = require('express'); // 创建应用对象 const app = express(); // 创建路由规则 // request是对请求报文的封装s // response是对响应报文的封装 app.all('/server', (request, response) => { // 定义数据模拟数据库返回的数据 const data = { id: 1, msg: '用户名存在' } value = JSON.stringify(data) response.end('lmk(' + value + ')') //将数据返回给客户端 }) app.listen(4000, () => { console.log('服务已启动,4000端口监听'); });
- 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> <input type="text"> <p></p> </body> <script> // 定义一个函数 传入data function lmk(data) { // 前端input失去焦点时会生成script标签去请求 服务端,服务端返回一个函数的调用并把结果传入给data // 在该函数中获取了服务端返回的数据,进行一个处理 input.style.border = '1px solid red'; //将 input的边框设置为红色 p.innerHTML = data.msg //p标签的文字设置为服务端返回的数据 //这样服务端就可以返回数据到前端,在前端进行一个操作 } // 获取元素 let input = document.querySelector('input'); let p = document.querySelector('p') // 绑定事件 input.addEventListener('blur', function() { // 获取input的信息,可以没有这一步 let user = this.value; // 创建一个script标签 const s = document.createElement('script'); // 更改这个标签的src属性 s.src = 'http://127.0.0.1:4000/server' // 在body标签最后生成刚刚创建的标签 document.body.append(s); }) </script> </html>
JQuery发送jsonp请求
- 服务端代码
// 引入 express const express = require('express'); // 创建应用对象 const app = express(); // 创建路由规则 app.all('/server', (request, response) => { // response.setHeader('Access-Control-Allow-Origin', '*'); // 定义返回数据 let data = { name: 'lmk' } // 将数据转为json字符串 data = JSON.stringify(data) // 接收 jQuery发送的callback参数(jQuery发送的参数默认变成了一个函数) let cb = request.query.callback; response.send(cb + '(' + data + ')') // 通过参数把返回数据传给前端 }) app.listen(4000, () => { console.log('服务已启动,4000端口监听'); });
- 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> <script src="./jquery.min.js"></script> </head> <style> div { width: 200px; height: 100px; border: 1px solid pink; } </style> <body> <button>发送请求</button> <div></div> </body> <script> // 通过按钮点击事件发送请求 $('button').click(function() { // 通过 该方法发送jsonp请求 后面必须带?callback=?参数,服务端可以接收到这个参数,只不过变为了一个函数,服务端使用这个函数就可以把数据传递给后面的function(data),在这里面进行数据处理 $.getJSON('http://127.0.0.1:4000/server?callback=?', function(data) { $('div').text(data.name) }) // 就是在发送请求时传入?callback=? 这个参数在传给服务器时就会变成一个函数,服务器通过在最后返回值调用这个函数并把数据传入,就可以在前端的回调函数中获取服务器传递的值了 }) </script> </html>
CORS
- 跨域资源共享,是官方的一个解决方案,特点是不需要在客户端进行特殊的操作,完全在服务端进行处理,支持get和post请求
- 跨域资源共享新增了一组http首部字段,允许服务器声明哪些源站可以通过浏览器有权限的访问哪些资源
CORS的工作原理
- 通过设置一个响应头告诉浏览器,该请求允许跨域,浏览器收到响应后就会对响应放行
// 服务端只需要添加响应头即可实现跨域
//这里以 Express举例
app.all('/server', (request, response) => {
response.setHeader('Access-Control-Allow-Origin', '*'); // 设置响应头 * 表示 允许所有 如果只想让某一个网页允许跨域的话*可以改为那个网页的http地址
response.setHeader('Access-Control-Allow-Headers', '*'); // 允许所有的请求头来请求
response.setHeader('Access-Control-Allow-Method', '*'); // 允许所有请求类型
// 一般加上这三行就可以完成请求跨域,还有好多响应头,可以查看 CORS相关文档
response.send('hello')
})
// 现在客户端就可以随便进行请求了
本博客所有文章是以学习为目的,如果有不对的地方可以一起交流沟通共同学习 邮箱:1248287831@qq.com!