文章目錄
問題描述
一般情況下,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>