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)}