各瀏覽器對 onbeforeunload 事件的支援與觸發條件實現有差異
問題描述
一般情況下,onbeforeunload 事件處理函式內會寫入一些提示性語句,當使用者的瀏覽器跳轉到其他頁面時,用來提醒使用者當前頁面將要跳轉,請使用者決定是否觀看新頁面。
或者在 onbeforeunload 事件內處理一些業務邏輯,在瀏覽器跳轉到新頁面之前 ,執行一些業務邏輯,如儲存使用者瀏覽資訊等。
簡單的說這個事件應僅在頁面 URL 發生變化時觸發,但是在 IE 中 使用 JavaScript 偽協議執行指令碼程式時,也會觸發 onbeforeunload 事件。
造成的影響
此問題不會造成大問題,但會導致不友好的提示出現,稍微影響使用者操作體驗。
受影響的瀏覽器
所有瀏覽器 |
---|
問題分析
onbeforeunload 事件是非 W3C DOM-Event 標準事件,它屬於 BOM (Browser Object Model) 範疇。到現在為止 BOM 還沒有被標準化,它由各個瀏覽器廠商制定,因此會有實現差異。
時至今日,HTML5 規範草案中已經開始標準化 BOM,遺憾的是 onbeforeunload 事件的觸發條件還沒有在草案中作出詳細說明。
更多內容可參考:6.1.6.2 Event handlers on elements, Document objects, and Window objects。
最初的 onbeforeunload 事件支援是由 IE4.0 版本提供,存在於 BODY、FRAMESET 的 DOM 物件及 window 物件之中,隨後被其他瀏覽器複製,但具體事件觸發方式並沒有統一。
根據 MSDN 中描述,IE 的 onbeforeunload 事件可由以下這些條件觸發:
- 關閉當前瀏覽器視窗。
- 導航到另一個進入一個新的地址或選擇一個喜歡的位置。
- 單擊後退,前進,重新整理,或主頁按鈕。
- 點選一個連結到新頁面。
- 呼叫 超連結的 click 方法。
- 呼叫 document.write 方法。
- 呼叫 document.open 方法。
- 呼叫 document.close 方法。
- 呼叫 window.close 方法。
- 呼叫 window.open 方法,視窗名稱設定值為 _self。
- 呼叫 window.navigate 或 NavigateAndFind 方法。
- 呼叫 location.replace 方法。
- 呼叫 location.reload 方法。
- 指定一個 location.href 屬性的新值。
- 使用 submit 按鍵提交表單,或呼叫 form.submit 方法。
更詳細的說明可以查考 MSDN 原文:onbeforeunload Event。
在這些觸發條件中絕大多數都使頁面產生了跳轉,但還缺少一些常見情況說明,即頁面 URL 可能發生了變化但沒有產生跳轉。比如 "javascipt:" "mailto:" 等常見的瀏覽器內建偽協議,以及由第三方或使用者自定義的為協議時,頁面並不跳轉,而是根據偽協議執行指定的行為。這個情況應加入到觸發條件中。
根據以上所有這些觸發條件,我們構建如下程式碼來檢測各瀏覽器對 onbeforeunload 事件的支援程度與觸發條件:
<script> window.onbeforeunload=function(){ return "請點選取消留在此頁"; } </script> 請手工關閉當前瀏覽器視窗。<br/> 請手工單擊後退,前進,重新整理,或主頁按鈕。<br/> 請手工在位址列輸入其他頁面地址或從收藏夾、歷史記錄中將頁面導航其他站點。<br/> <a href="http://www.google.com" id="A">點選一個連結到新頁面</a><br /> <button onclick="document.getElementById('A').click()">呼叫 anchor.click 方法</button><br /> <button onclick="document.write('A')">呼叫 document.write 方法</button><br /> <button onclick="document.open()">呼叫 document.open 方法</button><br /> <button onclick="document.close()">呼叫 document.close 方法。</button><br /> <button onclick="window.open('http://www.google.com','_self')">呼叫 window.open方法,視窗名稱設定值為 _self。</button><br /> <button onclick="try{window.navigate('http://www.google.com')}catch(e){alert('不支援此方法')}">呼叫 window.navigate 方法</button><br /> <button onclick="try{window.external.NavigateAndFind('http://www.google.com','','')}catch(e){alert('不支援此方法')}">呼叫 NavigateAndFind 方法</button><br /> <button onclick="location.replace('http://www.google.com')">呼叫 location.replace 方法</button><br /> <button onclick="location.reload()">呼叫 location.reload 方法</button><br /> <button onclick="location.href='http://www.google.com'">指定一個 location.href 屬性的新值</button><br /> <form action="http://www.google.com" id="B"> <input type="submit" value="提交具有action屬性的一個表單"> </form> <button onclick="document.getElementById('B').submit()">呼叫 form.submit 方法</button> <a href="javascript:">呼叫 javascipt: 偽協議</a><br /> <a href="mailto:">呼叫 mailto: 偽協議</a><br /> <a href="custom:">呼叫自定義偽協議</a>
執行結果彙總入表:
IE | Firefox | Chrome Safari | Opera | |
---|---|---|---|---|
關閉當前瀏覽器視窗 | 事件被觸發 | 事件被觸發 | 事件被觸發 | 不支援該事件 |
導航到另一個進入一個新的地址或選擇一個喜歡的位置 | 事件被觸發 | 事件被觸發 | 事件被觸發 | 不支援該事件 |
單擊後退,前進,重新整理,或主頁按鈕 | 事件被觸發 | 事件被觸發 | 事件被觸發 | 不支援該事件 |
點選一個連結到新頁面 | 事件被觸發 | 事件被觸發 | 事件被觸發 | 不支援該事件 |
呼叫 anchor.click方法 | 事件被觸發 | 不支援此方法1 | 不支援此方法1 | 不支援該事件 |
呼叫 document.write方法 | 事件被觸發 | 事件被觸發 | 事件未觸發 | 不支援該事件 |
呼叫 document.open方法 | 事件被觸發 | 事件被觸發 | 事件未觸發 | 不支援該事件 |
呼叫 document.close方法 | 事件未觸發 | 事件未觸發 | 事件未觸發 | 不支援該事件 |
呼叫 window.open方法,視窗名稱設定值為 _self | 事件被觸發 | 事件被觸發 | 事件被觸發 | 不支援該事件 |
呼叫 window.navigate | 事件被觸發 | 不支援此方法2 | 不支援此方法2 | 不支援該事件 |
呼叫 NavigateAndFind方法 | 事件被觸發 | 不支援此方法3 | 不支援此方法3 | 不支援此方法3 |
呼叫 location.replace 方法 | 事件被觸發 | 事件被觸發 | 事件被觸發 | 不支援該事件 |
呼叫 location.reload 方法 | 事件被觸發 | 事件被觸發 | 事件被觸發 | 不支援該事件 |
指定一個 location.href 屬性的新值 | 事件被觸發 | 事件被觸發 | 事件被觸發 | 不支援該事件 |
使用 submit 按鍵提交表單 | 事件被觸發 | 事件被觸發 | 事件被觸發 | 不支援該事件 |
呼叫 form.submit 方法 | 事件被觸發 | 事件被觸發 | 事件被觸發 | 不支援該事件 |
呼叫 javascipt: 偽協議 | 事件被觸發 | 事件未觸發 | 事件未觸發 | 不支援該事件 |
呼叫 mailto: 偽協議 | 事件未觸發 | 事件未觸發 | 事件被觸發 | 不支援該事件 |
呼叫自定義偽協議 | 事件被觸發 | 事件被觸發 | 事件被觸發 | 不支援該事件 |
注 1: 直接呼叫連結元素的 click 方法模擬滑鼠點選事件,只有 IE 和 Opera 支援,BX9052: IE Opera 支援使用 window.navigate 方法控制頁面跳轉 和SD9025: IE6 IE7 IE8 Opera 支援除 INPUT 和 BUTTON 元素以外的其他元素的 'click' 方法。
注 2: 使用 window.navigate 方法導航網頁僅被 IE Opera 支援,可參考 MSDN 原文:navigate Method。
注 3: NavigateAndFind 方法處於 window.external 物件中,external 物件也僅 IE 支援,可參考 MSDN 原文:NavigateAndFind Method 和本站文章BT9012: IE 的 external 物件提供的方法是 IE 特有的。
結合彙總表可以看出:
- Opera 並不支援 onbeforeunload 事件。
- Chrome Safari 在呼叫 document.write、document.open、document.close 方法以及 "javascipt:" 偽協議時,不會觸發 onbeforeunload 事件。
- Firefox 在呼叫 document.close 方法和 "javascipt:"、"mailto:" 偽協議時,不會觸發 onbeforeunload 事件。
- IE 瀏覽器在呼叫 document.close 方法和 "mailto:" 偽協議時,不會觸發 onbeforeunload 事件。
解決方案
onbeforeunload 事件還未標準化,各瀏覽器的支援以及事件觸發條件差異較多,需謹慎使用。
如必須在非 Opera 瀏覽器內使用該事件,應儘量避免在頁面中呼叫常見的 "javascrpt:" 以及其他偽協議,以此迴避不同瀏覽器中 onbeforeunload 事件被頻繁觸發。
參見
知識庫
相關問題
- BT9012: IE 的 external 物件提供的方法是 IE 特有的
- BX2032: 某些情況下瀏覽器不按照 "target" 屬性所指目標開啟協議連結
- BX2003: 特定的 URL 偽協議需安裝提供該協議的特定軟體才有效
- BX9052: IE Opera 支援使用 window.navigate 方法控制頁面跳轉
測試環境
作業系統版本: | Windows 7 Ultimate build 7600 |
---|---|
瀏覽器版本: | IE6 IE7 IE8 Firefox 3.6.10 Chrome 7.0.544.0 dev Safari 5.0.2 Opera 10.62 |
測試頁面: | onbeforeunload_event_differences.html |
本文更新時間: | 2010-10-13 |
關鍵字
javascipt URL Protocol onbeforeunload
轉載於:http://w3help.org/zh-cn/causes/BX2047
測試頁面程式碼:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<script>
window.onbeforeunload=function(){
return "請點選取消留在此頁";
}
</script>
<body>
請手工關閉當前瀏覽器視窗。<br/>
請手工單擊後退,前進,重新整理,或主頁按鈕。<br/>
請手工在位址列輸入其他頁面地址或從收藏夾、歷史記錄中將頁面導航其他站點。<br/>
<a href="http://www.google.com" id="A">點選一個連結到新頁面</a><br />
<button onclick="try{document.getElementById('A').click()}catch(e){alert('不支援此方法')}">呼叫 anchor.click 方法</button><br />
<button onclick="document.write('A')">呼叫 document.write 方法</button><br />
<button onclick="document.open()">呼叫 document.open 方法</button><br />
<button onclick="document.close()">呼叫 document.close 方法。</button><br />
<button onclick="window.open('http://www.google.com','_self')">呼叫 window.open方法,視窗名稱設定值為 _self。</button><br />
<button onclick="try{window.navigate('http://www.google.com')}catch(e){alert('不支援此方法')}">呼叫 window.navigate 方法</button><br />
<button onclick="try{window.external.NavigateAndFind('http://www.google.com','','')}catch(e){alert('不支援此方法')}">呼叫 NavigateAndFind 方法</button><br />
<button onclick="location.replace('http://www.google.com')">呼叫 location.replace 方法</button><br />
<button onclick="location.reload()">呼叫 location.reload 方法</button><br />
<button onclick="location.href='http://www.google.com'">指定一個 location.href 屬性的新值</button><br />
<form action="http://www.google.com" id="B">
<input type="submit" value="提交具有action屬性的一個表單">
</form>
<button onclick="document.getElementById('B').submit()">呼叫 form.submit 方法</button><br />
<a href="javascript:">呼叫 javascipt: 偽協議</a><br />
<a href="mailto:">呼叫 mailto: 偽協議</a><br />
<a href="custom:">呼叫自定義偽協議</a>
</body>
</html>
相關文章
- 驗證碼前端對各瀏覽器的支援前端瀏覽器
- XML DOM 瀏覽器差異概述XML瀏覽器
- 瀏覽器事件迴圈機制與Vue nextTick的實現瀏覽器事件Vue
- 瀏覽器極速模式和相容模式差異瀏覽器模式
- 條件註釋判斷瀏覽器版本瀏覽器
- Scala與Java差異(二)之條件控制與迴圈Java
- 瀏覽器的視窗大小被改變時觸發的事件window.onresize瀏覽器事件
- 瀏覽器與Node的事件迴圈(Event Loop)有何區別?瀏覽器事件OOP
- 前端面試之瀏覽器機制中觸發事件的三個階段前端面試瀏覽器事件
- 瀏覽器滑鼠事件瀏覽器事件
- 瀏覽器事件解析瀏覽器事件
- 使用瀏覽器事件瀏覽器事件
- Autofac實現有條件的DI
- 關於 Angular 開發時對主流瀏覽器支援的話題Angular瀏覽器
- JavaScript瀏覽器事件物件JavaScript瀏覽器事件物件
- 瀏覽器事件系統瀏覽器事件
- 瀏覽器中的事件迴圈瀏覽器事件
- 瀏覽器的事件環機制瀏覽器事件
- 圖解JVM實驗-觸發FullGC的幾個條件圖解JVMGC
- getElementsByClassName()方法的瀏覽器支援版本瀏覽器
- 前端迴流與重繪:概念及觸發條件前端
- vue-codemirror 實現文字差異比對Vue
- node的事件迴圈和瀏覽器的事件迴圈有什麼區別?事件瀏覽器
- 監聽瀏覽器的後退事件瀏覽器事件
- 針對neumann邊界條件的差分法程式碼
- JS實現瀏覽器列印WordJS瀏覽器
- 寫一個簡單的支援Node.js&瀏覽器的自定義事件庫Node.js瀏覽器事件
- 瀏覽器事件迴圈Event Loop瀏覽器事件OOP
- javascript事件迴圈(瀏覽器/node)JavaScript事件瀏覽器
- 微軟決定於2022年停止對 IE 瀏覽器的支援微軟瀏覽器
- 瀏覽器/nodeJS 中的事件環工作原理瀏覽器NodeJS事件
- 瀏覽器滾動條高度的獲取瀏覽器
- Node.js Event Loop與瀏覽器 Event Loop(事件環)Node.jsOOP瀏覽器事件
- 現代瀏覽器探祕(part4):事件處理瀏覽器事件
- 瀏覽器原生支援平滑滾動瀏覽器
- [譯] 瀏覽器中 CSS 支援指南瀏覽器CSS
- 從零實現的瀏覽器Web指令碼瀏覽器Web指令碼
- 線上json差異比較工具--遞迴比較兩個json的節點和值的差異,並支援差異數預覽和逐個檢視差異JSON遞迴
- openGauss資料與PostgreSQL的差異對比SQL