現象javascript
最近在作項目的時候碰到了使用window.open被瀏覽器攔截的狀況,搞得人無比鬱悶啊,雖然在本身的環境能夠對頁面進行放行,可是對用戶來講,不能要求用戶都來經過攔截。況且當出現攔截時,不少小白根本不知道發生了啥,不知道在哪裏看被攔截的頁面,簡直悲催啊~~。html
另外,能夠發現,當window.open爲用戶觸發事件內部或者加載時,不會被攔截,一旦將彈出代碼移動到ajax或者一段異步代碼內部,立刻就出現被攔截的表現了。java
緣由分析&深刻研究程序員
當瀏覽器檢測到非用戶操做產生的新彈出窗口,則會對其進行阻止。由於瀏覽器認爲這不是一個用戶但願看到的頁面。ajax
好比對js中直接執行的,以下代碼:chrome
js code:json
// 直接打開一個頁面 window.open('//www.baidu.com', '_blank');
瀏覽器 ie8 chrome 40 firefox 34 opera 27 safari 5.1.7
是否阻止彈出 N N Y Y Y 而對於以下代碼:
js code:瀏覽器
document.body.addEventListener('click', function() { window.open('//www.baidu.com', '_blank'); });
全部瀏覽器都不會攔截。安全
綜上所述,各瀏覽器對攔截時機的判斷不一致,而對於放在ajax回調中的代碼,反應又不相同了,這裏就再也不贅述。可是,被瀏覽器攔截咱們代碼中要彈出的窗口並非程序員所但願的。app
解決方案:
一、使用a標籤替代
給出以下函數,將此函數綁定到click的事件回調中,就能夠避免大部分瀏覽器對窗口彈出的攔截:
js code:
function newWin(url, id) {
var a = document.createElement('a'); a.setAttribute('href', url); a.setAttribute('target', '_blank'); a.setAttribute('id', id); // 防止反覆添加 if(!document.getElementById(id)) document.body.appendChild(a); a.click();
}
二、使用form的submit方法打開一個頁面
這種方法須要構造一個from,而後由js代碼觸發form的submit,將表單提交到一個新的頁面,代碼較長,在這裏就不寫了,你們知道有這種方案就好了。
你們注意,以上兩種方法不適合放在ajax的回調函數中,若是放在回調函數中,依然會被瀏覽器攔截。
三、終極解決方案--先彈出窗口,而後重定向
第三種方案,實際上是一種變通方案,核心思想是:先經過用戶點擊打開頁面,而後再對頁面進行重定向。示例代碼以下。
js code:
xx.addEventListener('click', function () { // 打開頁面,此處最好使用提示頁面 var newWin = window.open('loading page'); ajax().done(function() { // 重定向到目標頁面 newWin.location.href = 'target url'; }); });
以上方法實際上是打開了兩個地址,因此建議你們打開第一個地址的時候給出一個相似‘當前頁面正在加載中,請稍後。。’的簡單提示頁,這樣能夠避免打開兩次真正的目標頁面,讓用戶察覺到頁面的重定向。
解決方法二:
<a href="javascript:;" onclick="dialog();">點擊彈窗</a> <script> function dialog(){ $.ajax({ url: 'url', type: 'POST', dataType: 'json', async: false, // 此處必須定義爲同步 data: {param1: 'value1'}, success: function(data){ window.open(data.url, '_blank'); //發起彈窗 } }) } </script>
該方法弊端:實測能解決大部分瀏覽器的攔截問題,可是解決不了安全軟件的攔截(360不會攔截,可是QQ管家會攔截)