Ajax学习第五天——FormData及同源政策
背景:由前几天的学习可以知道,当对表单数据进行提交的时候,Ajax需要我们指明需要提交的属性及数据并进行拼接,在这之前,我们必须手动获取对应控件的相关内容,一旦数据量过大,就很容易造成拼接错误等问题,所以提出了FormData这一解决方案。
-
FormData对象的作用
1. 模拟HTML表单,相当于将HTML表单映射成表单对象,自动将表单对象中的数据拼接成请求参数的格式;
2. 异步上传二进制文件(例如:图片 视频及音频文件)。 -
FormData对象的使用
1. 准备HTML表单,不用设置请求地址及请求方式,也不用将input控件中的按钮设置为submit,设置为button即可,因为若设置为submit方式,表单会自动进行提交,从而使FormData不生效,值得注意的是,必须为需要提交数据的控件设置name属性;<form id="form"> <input type="text" name="username"> <input type="password" name="password"> <input type="button" id="btn" value="提交"> </form>
-
利用FormData构造函数,将HTML表单转化为FormData对象
var form = document.getElementById('form');
var formData = new FromData(form);
-
提交表单对象,采用此方法提交表单时,不支持get方法
xhr.send(formData);
- FormData对象的实例方法
- 获取表单对象中属性的值
formData.get('key');
- 设置表单对象中属性的值,如果表单控件不存在,则会自动创建这个表单属性
formData.set('key','value');
- 删除表单对象中属性的值
formData.delete('key');
- 向表单对象中追加属性值,它可以在空的表单对象中追加值
formData.append('key','value');
与 set 方法的区别:在属性名已存在的情况下,set 方法会覆盖已有键名的值,append 会保留两个值,但是服务器端需要响应的设置,否则,仍然传递最后一次的值。
- FormData对二进制文件的上传及文件上传进度的展示
代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
</head>
<body>
<div class="container">
<div class="form-group">
<label>请选择文件</label>
<input type="file" id="file">
<br/>
<div class="progress">
<div class="progress-bar" style="width: 0%;" id="progress">0%</div>
</div>
</div>
</div>
<script>
//获取文件控件
var file = document.getElementById('file');
//对文件控件田间发生改变事件
file.onchange = function () {
//创建空的FormData构造函数
var formData = new FormData();
//将file控件中选择的文件追加到formData中
// 第一个参数开发过程中由后端人员提供 第二个参数代表选择的文件
formData.append('attrName',this.files[0]);
//创建Ajax对象
var xhr = new XMLHttpRequest();
//配置Ajax对象
xhr.open('post','http://localhost/foemData');
//在文件上传的过程中持续触发
xhr.upload.onprogress = function(ev){
//ev.loaded 文件已经上传了多少
//ev.total 上传文件总大小
var pro = (ev.loaded / ev.total)*100+'%';
//获取进度条
var progress = document.getElementById('progress');
//设置进度条的宽度
progress.style.width = pro;
//设置进度条的数值
progress.innerHTML = pro;
}
xhr.send(formData);
xhr.onload = function(){
console.log(xhr.responseText);
}
}
</script>
</body>
</html>
- FormData文件上传图片即使预览
在我们将图片上传到服务器以后,服务器通常都会将图片地址作为响应数据传递到客户端,客户端可以从响应数据中获取图片地址,然后将图片再显示到页面中,值得注意的是,客户端得到地址后,需要动态的创建img标签,即首先var img = document.createElement('img');
,再采用box.appendChild(img);
的方式添加到页面上,如果直接将图片地址赋值给img的src,客户会看到图片的加载过程,影响用户体验;在服务端,同样的需要设置,应该引入表单解析对象,即formidable。
接下来是有关昨天做行政区联动碰到的问题,大相径庭。
- 同源政策
Ajax的请求限制:Ajax只能向自己的服务器发送请求,比如说,A网站的服务器端有A的HTML文件,B网站的服务器端有B的HTML页面,此时,A可以向自己的服务器发送Ajax请求,B也可以向自己的服务器发送Ajax请求,但是A不能向B的服务器发送Ajax请求,B也同理。 - 什么是同源
如果两个页面拥有相同的域名,协议及端口,那么我们称这两个页面是同源的,其中只要有一个不同,都是不同源的。 - 同源政策的目的
同源政策是为了保证用户信息的安全,防止恶意的网站窃取数据,最初的同源政策是指A网站在客户端防止的Cookie,B网站是不能访问的。 - 使用JSONP解决同源限制问题
JSONP:json with padding的简称 它不属于Ajax请求,但它可以模拟Ajax请求 - 使用JSONP解决同源限制问题的步骤
- 将不同源的服务器端请求地址写在script标签的src属性中,因为script标签不受同源政策的影响
<script src="www.example.com"></script>
- 服务器端响应数据必须是一个函数的调用,真正要发送给客户端的数据需要作为函数调用的参数
const data = 'fn({name:'zhangSan',age:'20'})';
res.send(data);
- 在客户端全局作用域下定义函数fn,这个函数需要写在script标签的前面
function fn(data){ }
- 在fn函数内部对服务器端返回的数据进行处理
function fn(data){console.log(data)}