1. ajax請求獲取response中的content-length
前提條件:
請求是跨域請求
現象:
通過 xhr.getResponseHeader('Content-Length')獲取該字段時報錯
Refused to get unsafe header "Content-Length"
原因:
W3C的 xhr 標準中做了限制,規定客戶端無法獲取 response 中的 Set-Cookie、Set-Cookie2這2個字段,無論是同域還是跨域請求;
W3C 的 cors 標準對于跨域請求也做了限制,規定對于跨域請求,客戶端允許獲取的response header字段只限于“simple response header”和“Access-Control-Expose-Headers” (兩個名詞的解釋見下方)。
詳細解釋: 詳細說明 form 網絡
引申:
CORS (跨域資源共享)
定義:
跨域資源共享(CORS) 是一種機制,它使用額外的 HTTP 頭來告訴瀏覽器 讓運行在一個 origin (domain) 上的Web應用被準許訪問來自不同源服務器上的指定的資源
服務端的相互請求不會出現跨域現象
什么情況下需要跨域資源共享:
- 由XMLHttpRequest或者Fetch發起的跨域HTTP請求
- web字體 css中通過@font-face使用跨域字體資源
- webGL貼圖
- 使用 drawImage 將 Images/video 畫面繪制到 canvas
- 樣式表
附帶身份憑證的請求:
Fetch 和 CORS有一個有趣的特征,可以基于HTTP cookies和HTTP認證信息發送身份憑證。 一版而言,對于跨域XMLHttpRequest或Fetch請求,瀏覽器不會發送身份憑證信息,如果要發送身份憑證信息,需要設置XMLHttpRequest的某個特殊標志位。
xhr.withCredentials = true
但是如果服務器響應的請求中沒有攜帶 Access-Control-Allow-Credentials: true,瀏覽器將不會把響應內容返回給請求的發送者。
附帶身份憑證的請求與通配符:
對于附帶身份憑證的請求,服務器不能把Access-Control-Allow-Origin的值設置為,如果設置成了,請求將會失敗。
HTTP 響應首部字段
Access-Control-Allow-Origin: <Origin> | *
Origin參數值指向了允許訪問該資源的外域url。對于不需要攜帶身份憑證的請求,服務器可以指定該字段的值為*,表示允許來自所有域的請求
Access-Control-Expose-Headers
在跨域訪問時,XMLHttpRequest對象的getResponseHeader()方法只能拿到一些最基本的響應頭,Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma,如果要訪問其他頭,則需要服務器設置本響應頭。
Access-Control-Expose-Headers讓服務器把允許瀏覽器訪問的頭放入白名單。
例如 Access-Control-Expose-Headers : Content-Length
XMLHttpRequest對象就能通過getResponseHeader()獲取Content-Length響應頭部值。
HTTP 請求首部字段
列出了可用于發起跨域請求的首部字段。請注意,這些首部字段無須手動設置。當開發者使用XMLHttpRequest對象發起跨域請求時,他們已經被設置就緒。
Origin 首部字段表明預檢請求或實際請求的源站。
origin 參數的值為源站URL。他不包含任何路徑信息,只是服務器名稱。
注意: 不管是否為跨域請求,ORIGIN字段總是被發送。
window.onerror 與跨域的關系
如果是window.onerror添加在監聽不同域下的代碼報錯(跨域文本), 那么onerror函數中不會顯示完整的錯誤信息,語法錯誤的細節將不會被展示出來取而代之的是'Script error.'
如果想要能顯示出詳細信息,則必須在服務端設置允許跨域'Access-Control-Allow-Origin:*'response header,還需要在script標簽上添加crossorigin 屬性
2. 點擊瀏覽器回退按鈕,在路由守衛鉤子 beforeRouteLeave()中調用next(false),路由沒有變化,但是里面寫的彈窗一閃而過,并沒有真實顯示出來
beforeRouteLeave(){
if(this.editing){
next(false);
this.$confirm('當前頁面中有未提交數據,確認離開頁面?','提示').then(res =>{
// 點擊確定
next();
}).catch(res=>{
next(false)
})
}else{
next();
}
}