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