AJAX(二)
一、各种发送AJAX请求
1.axios发送AJAX请求(重点)
安装axios: 脚手架目录npm i axios
先配置服务端,类型改成all,然后允许接收自定义请求头啥的
// (8)axios.html
app.all('/axios-server', (request, response) => {
//设置响应头
response.setHeader('Access-Control-Allow-Origin', '*');// 设置允许跨域
response.setHeader('Access-Control-Allow-Headers', '*');//接收自定义请求头
//响应一个数据
const data = { name: 'ht' };
let str = JSON.stringify(data); //对对象进行字符串转换
//设置响应体
response.send(str);
})
axios发送请求成功的值是一个封装好的响应对象:
我们想要的响应数据其实藏在response.data
中
来三个按钮:
<button>GET</button>
<button>POST</button>
<button>AJAX</button>
const get = document.querySelectorAll('button')[0];
const post = document.querySelectorAll('button')[1];
const ajax = document.querySelectorAll('button')[2];
(1)GET请求
get.onclick = function() {
//GET请求
axios.get('http://127.0.0.1:8000/axios-server',{
//url参数
params: {a:1,b:2},
//请求头信息
headers: {name:'zzy',age:18},
//......
}).then((response) => {
//请求成功的回调
console.log('全部响应结果:',response);
console.log('响应状态码:', response.status);
console.log('响应状态字符串:',response.statusText);
console.log('响应头信息:', response.headers);
console.log('响应体:', response.data);
})
}
(2)POST请求
第二个参数对象里写请求体,第三个参数对象里写url参数和其他信息
post.addEventListener('click', function() {
//POST请求
axios.post('http://127.0.0.1:8000/axios-server',{
//第二个参数对象里写请求体
username: 'zzy',
password: '123'
},{
//url参数
params: {a:1,b:2},
//请求头信息
headers: {name:'zzy',age:18}
})
})
(3)axios函数发送通用请求
ajax.onclick = function() {
// 通用请求
axios({
//请求方法
method: 'POST',
//url
url: 'http://127.0.0.1:8000/axios-server',
//url参数,传的是query类型参数,只是名字叫params
params: {a:1,b:2},
//请求头信息
headers: {name:'zzy',age:18},
//请求体参数
data :{
username: 'zzy',
password: '123'
},
//超时时间2秒
timeout:2000
}).then((response) =>{
console.log('全部响应结果:',response);
console.log('响应状态码:', response.status);
console.log('响应状态字符串:',response.statusText);
console.log('响应头信息:', response.headers);
console.log('响应体:', response.data);
})
}
2.fetch发送AJAX请求
fetch比较牛逼的地方
在于,它不想jquery和axios需要引入第三方库,它直接就能用,它就在window的内置对象中,直接就能用调用fetch函数。
fetch当然也有缺点
,那就是返回的数据需要包两层promise,还有就是IE不兼容fetch
服务端随便搞一个
app.all('/fetch-server', (request, response) => {
//设置响应头
response.setHeader('Access-Control-Allow-Origin', '*');// 设置允许跨域
response.setHeader('Access-Control-Allow-Headers', '*');//接收自定义请求头
//响应一个数据
const data = { name: 'ht' };
let str = JSON.stringify(data); //对对象进行字符串转换
//设置响应体
response.send(str);
})
这里参数在url那传,和axios不太一样,然后响应体拿到的的json字符串,需要转换一下。这里不太熟悉,回头好好看看promise
btn.onclick = function() {
fetch('http://127.0.0.1:8000/fetch-server?a=1&b=2',{
//请求方法
method: 'POST',
//请求头
headers: {name: 'zzy'},
//请求体
body: {
username: 'zzy',
password: '123'
}
}).then((response) => {
return response.json(); //把json字符串转换为js对象
}).then(response => { //第二个then处理上一个返回的正确结果
console.log(response);
});
}
3.JQuery发送AJAX请求
//GET请求
$('button').eq(0).click(function () {
$.get('http://127.0.0.1:8000/jquery-server',{
a:100,b:1000
},function (data) {//响应体
console.log(data);
},'json')//返回JSON类型
})
//POST请求
$('button').eq(1).click(function () {
$.post('http://127.0.0.1:8000/jquery-server',{
a:100,b:1000
},function (data) {//响应体
console.log(data);
})
})
//通用型方法ajax
$('button').eq(2).click(function () {
$.ajax({
//请求类型
type:'GET',
//url
url: 'http://127.0.0.1:8000/jquery-server',
//参数
data:{a:100,b:200},
//响应体结果设置
dataType:'json',
//成功的回调
success:function (data) {
console.log(data);
},
//超时时间
timeout:2000,
//失败的回调
error:function () {
console.log('出错了!');
},
//头信息设置
headers:{
name:"lw",
password:"lww"
}
});
})
二、同源策略
同源策略就是协议、域名、端口号必须完全相同,有一个不一样就是跨域
这个地方听的比较懵,简单记录一下吧
搞个9000端口,从home传入index.html页面
const express = require('express');
const app = express();
app.get('/home', (request, response) => {
//从home进来后,响应一个页面,这个页面里搞的东西都是同样的来源?
response.sendFile(__dirname + '/index.html'); //拼接的是路径,不要加点
})
app.get('/data', (request, response) => {
response.send('用户数据');
})
app.listen(9000, () => {
console.log('服务已经启动,9000端口监听中...奥里给');
})
在index.html中,因为是在home下的,所以直接向/data发送请求是可以拿到响应体的
btn.onclick = function() {
const xhr = new XMLHttpRequest();
//这里因为满足同源策略,所以url可以简写
xhr.open('GET', '/data');
xhr.send();
xhr.onreadystatechange = function() {
if(xhr.readyState === 4) {
if(xhr.status >= 200 && xhr.status < 300) {
console.log(xhr.response);
}
}
}
}
三、jsonp
理解不到位,暂时理解成响应体传过去原生js代码,可以解决跨域问题(通过script的src属性请求数据),但只能解决GET。而且这个也要和后端去配合,后端的响应体应该写成js代码才行,所以解决跨域问题用jsonp不多。更多情况是用脚手架的配置代理
1.原生jsonp
还是先搞个服务端,响应体传过去一个函数的调用
// (10)jsonp.html 检测用户名是否存在
app.all('/jsonp-server', (request, response) => {
//响应一个数据
const data = { exist: 1, msg: '用户名已存在' };
let str = JSON.stringify(data); //对对象进行字符串转换
//设置响应体
response.send(`handle(${str})`);
})
实现用户名校验(模拟一下请求js代码的过程,并不是真的校验),服务端的响应体是一个函数的调用,那么我们就应该有这个函数,所以首先要声明handle函数,然后创建script标签,利用其src属性请求数据。
用户名:<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 = '1px solid #f00';
p.innerHTML = data.msg;
p.style.color = 'red';
}
input.addEventListener('blur', function() {
let username = this.value;
//向服务器发送请求,监测用户名是否存在
//1.创建script标签
const script = document.createElement('script');
//2.设置标签的src属性
script.src = 'http://127.0.0.1:8000/jsonp-server';
//将script插入到文档中
document.body.appendChild(script);
})
</script>
2.JQuery发送jsonp请求
这块儿根本没懂是在干啥
服务端:
// (11)JQuery-jsonp.html
app.all('/jquery-jsonp-server', (request, response) => {
//响应一个数据
const data = { name: 'zzy', age: 18 };
let str = JSON.stringify(data); //对对象进行字符串转换
//接收callback参数
let callback = request.query.callback;
//返回结果,这个callback就相当于是个函数名,相当于handle
response.send(`${callback}(${str})`);
})
<button>点击发送jsonp请求</button>
<div id="result"></div>
<script>
$('button').eq(0).click(function() {
//使用jquery发送jsonp请求时url后面要加参数callback=?,这是一个固定写法
//Jquery中的getJSON,省去了jsonp中handle函数的定义,靠callback代替
//这个callback参数传过去,好像可以变成一个函数,奇怪
$.getJSON('http://127.0.0.1:8000/jquery-jsonp-server?callback=?',function(data){
$('#result').html(`
名称:${data.name}<br>
年龄:${data.age}
`)
})
})
</script>
四、CORS
跨域资源共享,全部都是服务端设置的东西
//设置响应头 设置允许跨域
response.setHeader("Access-Control-Allow-Origin","*");
//任意头部信息
response.setHeader("Access-Control-Allow-Headers","*");
//预请求结果缓存
response.setHeader("Access-Control-Max-Age","delta-seconds");
//跨域请求时是否携带验证信息
response.setHeader("Access-Control-Allow-Credentials","true");
//设置请求允许的方法
response.setHeader("Access-Control-Allow-Methods","*");
//暴露头部信息
response.setHeader("Access-Control-Expose-Headers","*");