window.open() 的作用是創建一個新的瀏覽器窗口用來打開相關的資源,這是一個原生的 Javascript API 接口。
有關 window.open() 的基本使用可以參考 mozilla 提供的 API 文檔:window.open 。
大部分現代的瀏覽器(泛指 Chrome / Firefox / IE 10+ / Safari)都默認開啟了阻止彈出窗口的策略,原因是 window.open 被廣告商濫用,嚴重影響用戶的使用。這個阻止彈出窗口的操作,並不是直接封殺 windw.open(),而是會根據用戶的行為來判斷這次 window.open() 是否屬於流氓操作。
如果是由用戶觸發的動作所引起的 window.open 就不會被瀏覽器所阻止,比如寫在 onclick 這些事件 handler 里的,但如果是代碼自己觸發的就會被阻止。
但是問題來了,如果是用戶點擊后,我們的程序需要運行一些代碼然后才執行 window.open() ,這種情況是否會被阻止呢?
對於這種情況,我們來做個簡單的例子,就是點擊按鈕之后將 window.open() 延遲一下,看看瀏覽器們有什么反應。
當延遲 100 毫秒的時候,Chrome 會讓窗口彈出,但是當延遲 2000 毫秒(即 2s )時這個操作會被阻止。經過多次試驗,我發現這個臨界值是 1000 毫秒。1000 毫秒的時候允許彈出框, 1001 毫秒的時候被阻止。
大家可以通過修改代碼中的延遲值來試。這個臨界值,在 Safari / Chrome / Firefox (都是 for Mac) 下測試,均通過,都是 1001 毫秒的時候被阻止。
結果拿到 IE 11 下測試,發現就算是 1 毫秒都會被阻止。
我們先撇開 IE 的差異,我嘗試把 setTimeout 轉換成一些邏輯的代碼放在 window.open() 前面。
整體來說,Safari / Chrome / Firefox (桌面版) , 對於用戶點擊事件后的 window.open() 有 1s 的延遲容忍度。
返回來測試了下 IE 11 的表現,發現:
setTimeout 內的 window.open() 一律都被阻止,哪怕只是延遲 1毫秒
對於邏輯運算的延遲則有比較大的容忍度,至少 3s 內依然被放行(沒有再繼續測試下去)
然后順便測試了下 Safari for iPad 8.0 的情況,發現:
根據用戶的設置(設置 -> Safari -> 阻止彈出窗口),無差別阻止或允許窗口的彈出窗。
如果用戶去掉了阻止彈出窗口的選項,那么無論是由用戶點擊的還是程序自行觸發的,通通會彈出一個下的窗口詢問用戶是否要打開新的窗口。
弄完之后得出的小結是:
如果是由用戶點擊觸發的 window.open() 代碼前面,可以加上少量簡單的邏輯代碼來運行,但請控制在執行時間為 1s 內。
不過由於各種原因,我們的 window.open() 會經常性的被阻止掉,雖說瀏覽器本身有對這個阻止事件做通知,但是由於用戶是白痴的我們最好也在界面上做一些通知告知用戶。我們可以利用 window.open () 的 return 值來判斷 window.open 的執行情況,window.open 的返回值是一個打開的新窗口對象的引用, 如果 window.open 的操作被阻止,那么它的返回值就是 undefined 。
我們知道了出現這種問題的原因,下面就給大家介紹幾種解決辦法:
1.表單提交的方式
var form = document.createElement('form'); form.action = 'www.baidu.com?id=1'; form.target = '_blank'; form.method = 'POST'; document.body.appendChild(form); form.submit();
這種方式,如果需要傳遞參數時,需要使用 POST 方法, 默認的 GET 方法無法傳遞參數。也就是新頁面的url中沒有參數部分。
另外,Ajax下載文件時也是用form 表單來模擬下載。
2.直接將打開窗口操作放在按鈕/鏈接的onclick事件中
<a href="javascript:void(0)" onclick="window.open(url)"></a>
3.延遲這個打開操作
setTimeout('window.open(url);', 500); // 延遲時間不能太短 否則也會被攔截
4.通過JS打開新窗口會被攔截,換一種實現方式
var tempwindow=window.open('_blank'); // 先打開頁面 tempwindow.location='http://www.baidu.com'; // 后更改頁面地址
