W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
彈窗(popup)是向用戶顯示其他文檔的最古老的方法之一。
基本上,你只需要運行:
window.open('https://javascript.info/')
……它將打開一個具有給定 URL 的新窗口。大多數(shù)現(xiàn)代瀏覽器都配置為在新選項卡中打開 url,而不是單獨的窗口。
彈窗自古以來就存在。最初的想法是,在不關(guān)閉主窗口的情況下顯示其他內(nèi)容。目前為止,還有其他方式可以實現(xiàn)這一點:我們可以使用 fetch 動態(tài)加載內(nèi)容,并將其顯示在動態(tài)生成的 <div>
中。彈窗并不是我們每天都會使用的東西。
并且,彈窗在移動設備上非常棘手,因為移動設備無法同時顯示多個窗口。
但仍然有一些任務在使用彈窗,例如進行 OAuth 授權(quán)(使用 Google/Facebook/… 登陸),因為:
在過去,很多惡意網(wǎng)站經(jīng)常濫用彈窗。一個不好的頁面可能會打開大量帶有廣告的彈窗。因此,現(xiàn)在大多數(shù)瀏覽器都會通過阻止彈窗來保護用戶。
如果彈窗是在用戶觸發(fā)的事件處理程序(如 onclick
)之外調(diào)用的,大多數(shù)瀏覽器都會阻止此類彈窗。
例如:
// 彈窗被阻止
window.open('https://javascript.info');
// 彈窗被允許
button.onclick = () => {
window.open('https://javascript.info');
};
這種方式可以在某種程度上保護用戶免受非必要的彈窗的影響,但是并沒有完全阻止該功能。
如果彈窗是從 onclick
打開的,但是在 setTimeout
之后,該怎么辦?這有點棘手。
試試運行一下這段代碼:
// 3 秒后打開彈窗
setTimeout(() => window.open('http://google.com'), 3000);
這個彈窗在 Chrome 中會被打開,但是在 Firefox 中會被阻止。
……如果我們減少延遲,則彈窗在 Firefox 中也會被打開:
// 1 秒后打開彈窗
setTimeout(() => window.open('http://google.com'), 1000);
區(qū)別在于 Firefox 可以接受 2000ms 或更短的延遲,但是超過這個時間 —— 則移除“信任”。所以,第一個彈窗被阻止,而第二個卻沒有。
打開一個彈窗的語法是 window.open(url, name, params)
:
?url
?
要在新窗口中加載的 URL。
?name
?
新窗口的名稱。每個窗口都有一個 ?window.name
?,在這里我們可以指定哪個窗口用于彈窗。如果已經(jīng)有一個這樣名字的窗口 —— 將在該窗口打開給定的 URL,否則會打開一個新窗口。
?params
?
新窗口的配置字符串。它包括設置,用逗號分隔。參數(shù)之間不能有空格,例如:?width=200,height=100
?。
params
的設置項:
left/top
?(數(shù)字)—— 屏幕上窗口的左上角的坐標。這有一個限制:不能將新窗口置于屏幕外(offscreen)。width/height
?(數(shù)字)—— 新窗口的寬度和高度。寬度/高度的最小值是有限制的,因此不可能創(chuàng)建一個不可見的窗口。menubar
?(yes/no)—— 顯示或隱藏新窗口的瀏覽器菜單。toolbar
?(yes/no)—— 顯示或隱藏新窗口的瀏覽器導航欄(后退,前進,重新加載等)。location
?(yes/no)—— 顯示或隱藏新窗口的 URL 字段。Firefox 和 IE 瀏覽器不允許默認隱藏它。status
?(yes/no)—— 顯示或隱藏狀態(tài)欄。同樣,大多數(shù)瀏覽器都強制顯示它。resizable
?(yes/no)—— 允許禁用新窗口大小調(diào)整。不建議使用。scrollbars
?(yes/no)—— 允許禁用新窗口的滾動條。不建議使用。還有一些不太受支持的特定于瀏覽器的功能,通常不使用。通常不使用這些功能。更多示例請見 MDN 中的 window.open。
讓我們打開一個包含最小功能集的新窗口,來看看哪些功能是瀏覽器允許禁用的:
let params = `scrollbars=no,resizable=no,status=no,location=no,toolbar=no,menubar=no,
width=0,height=0,left=-1000,top=-1000`;
open('/', 'test', params);
在這里,大多數(shù)“窗口功能”都被禁用了,并且窗口位于屏幕外。運行它,看看會發(fā)生什么。大多數(shù)瀏覽器都會“修復”奇怪的東西,例如 width/height
為零以及脫離屏幕(offscreen)的 left/top
設置。例如,Chrome 打開了一個全 width/height
的窗口,使其占滿整個屏幕。
讓我們添加正常的定位選項和合理的 width
、height
、left
和 top
坐標:
let params = `scrollbars=no,resizable=no,status=no,location=no,toolbar=no,menubar=no,
width=600,height=300,left=100,top=100`;
open('/', 'test', params);
大多數(shù)瀏覽器會根據(jù)要求顯示上面的示例。
設置中的省略規(guī)則:
open
? 調(diào)用中沒有第三個參數(shù),或者它是空的,則使用默認的窗口參數(shù)。yes/no
? 功能被省略了,那么被省略的功能則被默認值為 ?no
?。因此,如果你指定參數(shù),請確保將所有必需的功能明確設置為 ?yes
?。left/top
?,那么瀏覽器會嘗試在最后打開的窗口附近打開一個新窗口。width/height
?,那么新窗口的大小將與上次打開的窗口大小相同。open
調(diào)用會返回對新窗口的引用。它可以用來操縱彈窗的屬性,更改位置,甚至更多操作。
在下面這個示例中,我們從 JavaScript 中生成彈窗:
let newWin = window.open("about:blank", "hello", "width=200,height=200");
newWin.document.write("Hello, world!");
這里,我們在其加載完成后,修改其中的內(nèi)容:
let newWindow = open('/', 'example', 'width=300,height=300')
newWindow.focus();
alert(newWindow.location.href); // (*) about:blank,加載尚未開始
newWindow.onload = function() {
let html = `<div style="font-size:30px">Welcome!</div>`;
newWindow.document.body.insertAdjacentHTML('afterbegin', html);
};
請注意:在剛剛進行了 window.open
的時候,新窗口還沒有加載完成。我們可以通過 (*)
行中的 alert
證實這一點。因此,我們需要等待 onload
以對新窗口進行更改。我們也可以對 newWin.document
使用 DOMContentLoaded
處理程序。
同源策略
只有在窗口是同源的時,窗口才能自由訪問彼此的內(nèi)容(
相同的協(xié)議://domain:port
)。
否則,例如,如果主窗口來自于
site.com
,彈窗來自于gmail.com
,則處于安全性考慮,這兩個窗口不能訪問彼此的內(nèi)容。有關(guān)詳細信息,請參見 跨窗口通信 一章。
彈窗也可以使用 window.opener
來訪問 opener 窗口。除了彈窗之外,對其他所有窗口來說,window.opener
均為 null
。
如果你運行下面這段代碼,它將用 “Test” 替換 opener(也就是當前的)窗口的內(nèi)容:
let newWin = window.open("about:blank", "hello", "width=200,height=200");
newWin.document.write(
"<script>window.opener.document.body.innerHTML = 'Test'<\/script>"
);
所以,窗口之間的連接是雙向的:主窗口和彈窗之間相互引用。
關(guān)閉一個窗口:win.close()
。
檢查一個窗口是否被關(guān)閉:win.closed
。
從技術(shù)上講,close()
方法可用于任何 window
,但是如果 window
不是通過 window.open()
創(chuàng)建的,那么大多數(shù)瀏覽器都會忽略 window.close()
。因此,close()
只對彈窗起作用。
如果窗口被關(guān)閉了,那么 closed
屬性則為 true
。這對于檢查彈窗(或主窗口)是否仍處于打開狀態(tài)很有用。用戶可以隨時關(guān)閉它,我們的代碼應該考慮到這種可能性。
這段代碼加載并關(guān)閉了窗口:
let newWindow = open('/', 'example', 'width=300,height=300');
newWindow.onload = function() {
newWindow.close();
alert(newWindow.closed); // true
};
有一些方法可以移動一個窗口,或者調(diào)整一個窗口的大?。?/p>
?win.moveBy(x,y)
?
將窗口相對于當前位置向右移動 x 像素,并向下移動 y 像素。允許負值(向上/向左移動)。
?win.moveTo(x,y)
?
將窗口移動到屏幕上的坐標 (x,y) 處。
?win.resizeBy(width,height)
?
根據(jù)給定的相對于當前大小的 width/height 調(diào)整窗口大小。允許負值。
?win.resizeTo(width,height)
?
將窗口調(diào)整為給定的大小。
還有 window.onresize
事件。
僅對于彈窗
為了防止濫用,瀏覽器通常會阻止這些方法。它們僅在我們打開的,沒有其他選項卡的彈窗中能夠可靠地工作。
沒有最小化/最大化
JavaScript 無法最小化或者最大化一個窗口。這些操作系統(tǒng)級別的功能對于前端開發(fā)者而言是隱藏的。
移動或者調(diào)整大小的方法不適用于最小化/最大化的窗口。
我們已經(jīng)在 Window 大小和滾動 一章中討論過了滾動窗口。
?win.scrollBy(x,y)
?
相對于當前位置,將窗口向右滾動 ?x
? 像素,并向下滾動 ?y
? 像素。允許負值。
?win.scrollTo(x,y)
?
將窗口滾動到給定坐標 ?(x,y)
?。
?elem.scrollIntoView(top = true)
?
滾動窗口,使 ?elem
? 顯示在 ?elem.scrollIntoView(false)
? 的頂部(默認)或底部。
這里也有 window.onscroll
事件。
從理論上講,使用 window.focus()
和 window.blur()
方法可以使窗口獲得或失去焦點。此外,這里還有 focus/blur
事件,可以捕獲到訪問者聚焦到一個窗口和切換到其他地方的時刻。
盡管,在實際中它們被進行了嚴格地限制,因為在過去,惡意網(wǎng)站濫用這些方法。
例如,看下面這段代碼:
window.onblur = () => window.focus();
當用戶嘗試從窗口切換出去(window.onblur
)時,這段代碼又讓窗口重新獲得了焦點。目的是將用戶“鎖定”在 window
中。
因此,瀏覽器必須引入很多限制,以禁用此類代碼并保護用戶免受廣告和惡意頁面的侵害。具體則取決于瀏覽器。
例如,移動端瀏覽器通常會完全忽略 window.focus()
。并且,當彈窗是在單獨的選項卡而不是新窗口中打開時,也無法進行聚焦。
盡管如此,在某些情況下,此類調(diào)用確實有效且很有用。
例如:
newWindow.focus()
? 是個好主意。以防萬一,對于某些操作系統(tǒng)/瀏覽器組合(combination),它可以確保用戶現(xiàn)在位于新窗口中。window.onfocus/onblur
?。這使我們可以暫停/恢復頁面活動和動畫等。但是請注意,?blur
? 事件意味著訪問者從窗口切換了出來,但他們?nèi)匀豢梢杂^察到它。窗口處在背景中,但可能仍然是可見的。彈窗很少使用,因為有其他選擇:在頁面內(nèi)或在 iframe 中加載和顯示信息。
如果我們要打開一個彈窗,將其告知用戶是一個好的實踐。在鏈接或按鈕附近的“打開窗口”圖標可以讓用戶免受焦點轉(zhuǎn)移的困擾,并使用戶知道點擊它會彈出一個新窗口。
open(url, name, params)
? 調(diào)用打開一個彈窗。它會返回對新打開的窗口的引用。open
? 調(diào)用。通常會顯示一條通知,以便用戶可以允許它們。window.opener
? 屬性訪問 opener 窗口(譯注:即打開彈窗的窗口)。要關(guān)閉彈窗:使用 close()
調(diào)用。用戶也可以關(guān)閉彈窗(就像任何其他窗口一樣)。關(guān)閉之后,window.closed
為 true
。
focus()
? 和 ?blur()
? 方法允許聚焦/失焦于窗口。但它們并不是一直都有效。focus
?和 ?blur
? 事件允許跟蹤窗口的切換。但是請注意,在 ?blur
? 之后,即使窗口在背景狀態(tài)下,窗口仍有可能是可見的。Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: