Ajax来源
浏览器和服务器间的关系

数据起始是在服务器中,当用户点击后,从服务器发送过来。
可通过form表单发送数据:
<form action="/.getData.php" method="get">
action指定提交的url,method提交的方式
form通过get提交数据的本质:
在url?后拼接上key=value
form只有在设置了name属性的表单元素才能在提交表单的时候传递他们的值
- form
- enctype属性
- 规定在发送表单数据之前如何对其进行编码
- 默认值是:application/x-www/form-urlencoded(在发送前编码所有字符)
- 提交文件:multipart/form-data
- 不对字符编码。当文件格式是这个的时候,必须使用改值
- text/plain:空格转换为“+”,但不对特殊字符编码
- enctype属性
用form点击submit自动就发送出去了,没有设置 请求行 请求主体等。缺点:一点击页面就跳转了。
想要页面不刷新实现局部刷新用ajax:就需要自己发送一个请求报文:即请求头 请求行 请求主体
HTTP协议
概念:使用请求报文和响应报文这种方式进行数据交互称为http协议。
http协议就是规定了请求报文和响应报文的格式
请求报文
浏览器发出。保存的是发送的方法,请求的url地址以及浏览器的信息和返送给服务器的数据。
请求报文=请求头+请求行+请求主体。
- 请求行
请求方式,请求地址 - 请求头
- Accept 浏览器的信息
- Accept-Encoding 接收的语言格式
- Accept-Language 发送的语言格式
- 等一些浏览器信息 以及想要发送给服务器的信息
- 请求主体
发送给服务器的数据内容
响应报文
服务器返回的。主要是服务器的信息,浏览器可以直接看到的内容
响应报文=状态行+响应头+响应主体
- 状态行
请求是否成功
请求的状态:200成功,404页面不存在,304被缓存了 - 响应头
服务器的一些信息。(服务器想要告诉浏览器的一些信息) - 响应主体
用户能看到的内容
Ajax实现
Ajax请求
- 创建异步对象 XMLHttpRequest
- 设置请求行(get请求写在url后面).open
- 设置请求头(get请求可以省略,post不发送数据也可以省略) .setRequestHeader
- 注册回调函数 onload 异步对象.responseText
- 请求主体发送 .send(get请求为空,或者写null;post请求数据写在这里,如果没有数据,直接为空或null)
Ajax通过post发送请求
var xhr = new XMLHttpRequest;
xhr.open('post','postData.php')
xhr.setRequestHeader('Content-type','application/x-www-form-unlencoded')
//是表单form的entype的默认值
xhr.onload = function(){ console.log(xhr.responseText); }
xhr.send('key1value1&key2=value2')//发送数据
Ajax通过get发送请求
var xhr = new XMLHttpRequest;
xhr.open('get','getData.php?key1=value1&key2=value2') //请求的数据在这里发送
//不用设置请求头
xhr.onload=function(){
console.log(xhr.responseText);
}
xhr.send(null)//或xhr.send()
//此处什么都不发,因为请求的数据写在了url里面
onreadystatechange
状态改变事件
- 只要readyState属性发生变化,就会调用相应的处理函数
- 所有浏览器都支持onreadystatechange
- 后来许多浏览器实现了额外的事件(onload,onerror,onprogress)
- onload,IE有兼容问题
xhr.onreadystatechange = function(){} (替换onload)
readyState属性
0 XMLHttpRequest代理已被创建,还没有调用open()方法
1 open()方法已被调用
2 send()方法已经被调用,并且头部和状态语句可获得
3 下载中,responseText属性语句包含部分数据
4 下载完成
即 与ajax创建的步骤一样,一共四步骤
get&post
get方式请求数据
- 数据是拼接在url中的,数据的安全性不好
- 数据的长度问题
- 有些浏览器会限制url的长度
- 有些服务器,对于长度太长的url直接屏蔽了
- 优点:测试方便
post方式请求数据
- 提交的数据不在url中,安全性好一些
- 没有长度限制
- 如果要上传文件,必须使用post
get还是post
- 如果追求速度,用get发送只有少数剪短字段的小表单
- 如果传递的是需要立即执行的命令行参数,会限制其数目或长度,对那些很多字段或很长的文本域,用post
- 若出于安全性考虑用post。用get可从地址栏和服务器的日志文件中进行截取。post在将参数传输给服务器的时候,可用加密方式
Ajax的封装
function ajax(option){
//获取默认值
var url = option.url;//请求路径
if(!url){
console.error('请求路径必须传入');
return;
}
var method = (option.method||'get').toLowerCase();//请求方法
var data = option.data||{};
//处理请求参数/请求主体
var params = ""
for(var key in data){
params+=key+"="+data[key]+"&"
}
params = params.slice(0,-1);
//获取响应成功的回调函数
var success = option.success;
//获取响应出错的回调函数
var error = option.error
//获取是否使用xhr进去数据请求
var dataType = (option.dataType||'json').toLowerCase();
//如果使用script标签请求数据,传给后台的回调函数名的键,默认是callback
var jsonp = option.jsonp||'callback';
//如果使用script标签请求数据,传给后台的回调函数名,默认是随机
var cb = option.cb||('phone'+new Date().getTime()+Math.random().toString().slice(2));
//如果使用xhr对象(json)请求数据
if(dataType=="json"){
//创建xhr对象
var xhr = new XMLHttpRequest;
//请求
if(method=="get"){
xhr.open('get',url+"?"+params);
xhr.send(null)
}
if(method=="post"){
xhr.open('post',url);
xhr.setRequestHeader("content-type","application/x-www-form-urlencoded");
xhr.send(params)
}
//响应
xhr.onreadystatechange = function(){
if(xhr.readyState==4){
if(xhr.status==200){
success(xhr.response);
}else{
if(error){
error();
}
}
}
}
}
//如果使用script标签请求(jsonp)数据
//创建script标签
var script = document.createElement('script');
//设置该标签的src属性
script.src =url+"?"+params+"&"+jsonp+"="+cb;
//定义一个函数,以备调用
window[cb] = function(data){
success(data);
script.remove()
}
document.body.appendChild(script);
}
// ajax({
// method:"get/post",//请求方式是get或者post,不区分大小写,默认get
// url:"",//请求的路径,不需要参数
// data:{
// a:1,
// b:2
// },//请求参数或者请求主体
// success:function(res){
// //响应完成或的回调函数,res指的是响应的数据
// },
// error:function(){
// },
// dataType:'json/jsonp',//指定是使用xhr请求(json)数据还是使用script标签请求(jsonp)数据
// jsonp:"",//如果使用script标签请求数据,传给后台的回调函数名的键,默认是callback
// cb://如果使用script标签请求数据,传给后台的回调函数名,默认是随机
// })
跨域问题
1、 什么是跨域?
跨域是指浏览器不能执行其他网站的脚本。它是由浏览器的同源政策造成的,是浏览器对象JavaScript施加的安全限制
- 同源策略:是指协议、域名、端口要相同,只有三者有一个不同就产生跨域
- 浏览器为了安全问题一般都限制了跨域访问,也就是不允许跨域请求资源。注:跨域限制访问,事实上是浏览器的限制策略,理解这一点很重要
2、三种方式解决跨域问题
- JSONP(需要前后端配合完成)
- 前端使用script标签来调用接口
- 后端需要配合使用res.jsonp()返回数据
- JSON只适用于GET请求,POST请求用不了
//第一种写法
<script>
function handleData(res) { console.log('res',res) }
</script>
//第二种写法
<script>
function handleData(res){ console.log('res',res) }
var oScript = document.createElement('script');
oScript.src = "http://localhost:8001/user/list?callback=handleData";
oScript.type = "text/javascript";
document.body.appendChild(oScript);
</script>
- 代理:使用http-proxy-middleware中间件来实现代理
- 在Node.js中使用http-proxy-middleware来进行接口代理
- 后端还可以使用Nginx进行接口处理
- 前端可以使用webpack进行接口代理
const app = require('express')();
const proxy = require('http-proxy-middleware');
app.use('/user',proxy({
target:'http://10.36.136.170:9999',
changeOrigin:true}))
- CORS
- 只需要后端工程师来处理
const app = require('express')();
//设置跨域访问(前端需要清除缓存后,才能再测试跨域)
app.all('*',function(req,res,next){
res.header("Access-Control-Allow-Origin","*");
res.header("Access-Control-Allow-Headers","X-Requested-Width");
res.header("Access-Control-Medthods","PUT,POST,GET,DELETE,OPTIONS");
res.header("X-Powered-By","3.2.1");
res.header("Content-Type","application/json;charset=utf-8");
next();
});