var REPORT_URL = '//gamepre.ltyun.cc/api/public/page-data/save?' //數據上報接口
var img = new Image; //建立img標籤
img.onload = img.onerror = function(){ //img加載完成或加載src失敗時的處理
img = null; //img置空,不會循環觸發onload/onerror
};
img.src = REPORT_URL + Build._format(params); //數據上報接口地址拼接上報參數做爲img的src
複製代碼
有時,img標籤中的src圖片加載失敗,原來的圖片位置會出現一個碎片圖標,用戶體驗會降低。javascript
要想去除載入圖片失敗時顯示在左上角的碎片圖標,就要借用img標籤的onerror事件和javascript,img標籤支持onerror 事件,在裝載文檔或圖像的過程當中若是發生了錯誤,就會觸發onerror事件。可使用一張提示錯誤的圖片代替載入失敗的圖片。代碼以下:php
<img src="images/bg.png" onerror="javascript:this.src='images/bgError.png';">
複製代碼
當src默認的src不存在時,就會觸發onerror事件,在該事件中指定img.src。html
但問題來了,若是 bgError.png也不存在,則繼續觸發 onerror事件,致使循環,故出現錯誤。前端
解決方法:java
第一種:去掉 onerror 代碼;或者更改 onerror 代碼爲其它;或者確保 onerror 中的圖片足夠小,而且存在.ajax
第二種:img=img.onLoad=img.onError=nulljson
不少地方不使用Ajax發送請求上報數據而使用img標籤,主要有如下兩個緣由:api
由於img不存在跨域的問題,因此不少網站也作了圖片的防盜鏈處理,好比百度、知乎是有處理的,博客園應該是沒有相應處理的。跨域
跨域,指的是瀏覽器對於javascript的同源策略的限制,是瀏覽器施加的安全限制。所謂同源是指協議,域名,端口均相同。瀏覽器
http://www.123.com/index.html 調用 http://www.123.com/server.php (非跨域)
http://www.123.com/index.html 調用 https://www.123.com/server.php (協議不一樣,跨域)
http://www.123.com/index.html 調用 http://www.456.com/server.php( 主域名不一樣,跨域)
http://abc.123.com/index.html 調用 http://def.123.com/server.php (子域名不一樣,跨域)
http://localhost:8080/index.html 調用 http://localhost:8081/server.php (端口不一樣,跨域)
http://localhost:8080/index.html 調用 http://127.0.0.1:8081/server.php (域名不一樣,跨域)
請注意:localhost和127.0.0.1雖然都指向本機,但也屬於跨域。
容許跨域加載資源的有三個標籤。分別是:
瀏覽器同源策略有兩種限制,其限制之一是不能經過ajax的方法去請求不一樣源中的文檔。 第二個限制是瀏覽器中不一樣域的框架之間不能進行js的交互操做的,咱們主要解決第一種限制Ajax跨域。
實現以下:
<script type="text/javascript">
var messagetow = function(data){
//data 經過跨域獲得的信息
console.log(data);
};
var url = "gamepre.ltyun.cc/api/public/page-data/save?callback=messagetow";
var script = document.createElement('script');
script.setAttribute('src', url);
document.getElementsByTagName('head')[0].appendChild(script);
</script>
複製代碼
它容許瀏覽器向跨源服務器,發出XMLHttpRequest
請求,從而克服了AJAX只能同源使用的限制。CORS須要瀏覽器和服務器同時支持。目前,全部瀏覽器都支持該功能,IE瀏覽器不能低於IE10。
整個CORS通訊過程,都是瀏覽器自動完成,不須要用戶參與。對於前端開發者來講,CORS通訊與同源的AJAX通訊沒有差異,代碼徹底同樣。瀏覽器一旦發現AJAX請求跨源,就會自動添加一些附加的頭信息,有時還會多出一次附加的請求,但用戶不會有感受。
所以,實現CORS通訊的關鍵是服務器。只要服務器實現了CORS接口,就能夠跨源通訊。
跨域請求有兩種形式:
一、 簡單請求 二、 非簡單請求
簡單請求知足如下條件:
HTTP請求方法(區分大小寫)爲如下之一:
· HEAD · GET · POST
HTTP頭部匹配(不區分大寫小)爲如下:
· Accept
· Accept-Language
· Content-Language
· Last-Event-ID
· Content-Type: 只限於三個值application/x-www-form-urlencoded、multipart/form-data、text/plain
對於簡單請求,瀏覽器直接發出CORS請求。具體來講,就是自動在頭信息之中,增長一個Origin字段。
GET /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
複製代碼
上面的頭信息中,Origin字段用來講明,本次請求來自哪一個源(協議 + 域名 + 端口)。服務器根據這個值,決定是否贊成此次請求。
若是Origin
指定的源,不在許可範圍內,服務器會返回一個正常的HTTP迴應。瀏覽器發現,這個迴應的頭信息沒有包含Access-Control-Allow-Origin
字段,就知道出錯了,從而拋出一個錯誤,被XMLHttpRequest
的onerror
回調函數捕獲。注意,這種錯誤沒法經過狀態碼識別,由於HTTP迴應的狀態碼有多是200。
若是Origin
指定的域名在許可範圍內,服務器返回的響應,會多出幾個頭信息字段。
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Credentials: true //布爾值,是否容許發送cookie,默認cros中不包含
Access-Control-Expose-Headers: FooBar //header除默承認獲取字段
Content-Type: text/html; charset=utf-8
複製代碼
withCredentials 屬性
CORS請求默認不發送Cookie和HTTP認證信息。若是要把Cookie發到服務器,一方面要服務器贊成,指定Access-Control-Allow-Credentials:true。另外一方面,開發者必須在AJAX請求中打開withCredentials屬性。
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
複製代碼
咱們想使用PUT或者DELETE請求,又或者咱們想使用Content-Type:application/json來支持JSON。那麼,咱們就須要非簡單請求。
咱們在使用非簡單請求時,表面上看起來客戶端只發送了一個請求,但實際上,要完成一次非簡單請求,客戶端在私底下是要向服務器發起兩次請求的。第一次請求("預檢"請求),是向服務器確認權限,一旦被受權,則發起第二次請求(真正意義上的數據請求)。且,第一次請求也能夠被緩存,因此不是每次咱們發起非簡單請求,都會預請求一次。
預檢請求的HTTP頭信息:
OPTIONS /cors HTTP/1.1 //請求方法是OPTIONS,表示這個請求是用來詢問的
Origin: http://api.bob.com
Access-Control-Request-Method: PUT //CORS請求會用到哪些HTTP方法
Access-Control-Request-Headers: X-Custom-Header //逗號分隔的字符串,指定瀏覽器CORS請求會額外發送的頭信息字段
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive //告訴WEB服務器或者代理服務器,在完成本次請求的響應後,保持鏈接,等待本次鏈接的後續請求
User-Agent: Mozilla/5.0...
複製代碼
服務器收到"預檢"請求之後,檢查了Origin
、Access-Control-Request-Method
和Access-Control-Request-Headers
字段之後,確認容許跨源請求,就能夠作出迴應。
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://api.bob.com //該字段設爲星號時,表示贊成任意跨源請求。
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain
複製代碼
若是瀏覽器否認了"預檢"請求,會返回一個正常的HTTP迴應,可是沒有任何CORS相關的頭信息字段。這時,瀏覽器就會認定,服務器不一樣意預檢請求,所以觸發一個錯誤,被XMLHttpRequest
對象的onerror
回調函數捕獲。控制檯會打印出以下的報錯信息。
XMLHttpRequest cannot load http://api.alice.com.
Origin http://api.bob.com is not allowed by Access-Control-Allow-Origin.
複製代碼
一旦預檢查獲得受權信息,那麼瀏覽器就會發送真正的跨域請求了。且,請求和服務器響應與簡單CORS請求同樣。
參考跨域資源共享 CORS 詳解,更多詳情點擊查看