JS高程:讀書(shū)摘要(十四)拖放、音視頻

一、 跨文檔消息傳遞

跨文檔消息傳送(cross-document messaging),有時(shí)候簡(jiǎn)稱為XDM,指的是在來(lái)自不同域的頁(yè)面間傳遞消息。

XDM 的核心是postMessage()方法,向另一個(gè)地方(包含在當(dāng)前頁(yè)面中的<iframe>元素,或者由當(dāng)前頁(yè)面彈出的窗口。)傳遞數(shù)據(jù)。

otherWindow.postMessage(message, targetOrigin, [transfer]);

  • otherWindow:其他窗口的一個(gè)引用,比如iframecontentWindow屬性、執(zhí)行window.open返回的窗口對(duì)象、或者是命名過(guò)或數(shù)值索引的window.frames。
  • message : 將要發(fā)送到其他 window的數(shù)據(jù)。它將會(huì)被結(jié)構(gòu)化克隆算法序列化。這意味著你可以不受什么限制的將數(shù)據(jù)對(duì)象安全的傳送給目標(biāo)窗口而無(wú)需自己序列化。

  • targetOrigin:通過(guò)窗口的origin屬性來(lái)指定哪些窗口能接收到消息事件,其值可以是字符串"*"(表示無(wú)限制,不建議使用)或者一個(gè)URI。如果目標(biāo)窗口的協(xié)議、主機(jī)地址或端口這三者的任意一項(xiàng)不匹配targetOrigin提供的值,那么消息就不會(huì)被發(fā)送;只有三者完全匹配,消息才會(huì)被發(fā)送。這個(gè)機(jī)制用來(lái)控制消息可以發(fā)送到哪些窗口(非常重要);

  • transfer[可選]:是一串和message同時(shí)傳遞的 Transferable 對(duì)象. 這些對(duì)象的所有權(quán)將被轉(zhuǎn)移給消息的接收方,而發(fā)送一方將不再保有所有權(quán)。

接收到XDM消息時(shí),會(huì)觸發(fā)window對(duì)象的message事件。這個(gè)事件是以異步形式觸發(fā)的,因此從發(fā)送消息到接收消息(觸發(fā)接收窗口的message事件)可能要經(jīng)過(guò)一段時(shí)間的延遲。觸發(fā)message事件后,傳遞給onmessage處理程序的事件對(duì)象包含以下三方面的重要信息。

  • data:從其他 window中傳遞過(guò)來(lái)的對(duì)象。
  • origin:調(diào)用 postMessage 時(shí)消息發(fā)送方窗口的 origin. 這個(gè)字符串由 協(xié)議、域名、端口號(hào)拼接而成。端口號(hào)(443https的默認(rèn)值)
  • source:對(duì)發(fā)送消息的窗口對(duì)象的引用; 可以使用此來(lái)在具有不同origin的兩個(gè)窗口之間建立雙向通信。

安全相關(guān):如果您不希望從其他網(wǎng)站接收message,請(qǐng)不要為message事件添加任何事件偵聽(tīng)器。 這是一個(gè)完全萬(wàn)無(wú)一失的方式來(lái)避免安全問(wèn)題;如果您確實(shí)希望從其他網(wǎng)站接收message,請(qǐng)始終使用originsource屬性驗(yàn)證發(fā)件人的身份。 當(dāng)您使用postMessage將數(shù)據(jù)發(fā)送到其他窗口時(shí),始終指定精確的目標(biāo)origin,而不是"*"。

//  示例:
// 主窗口域名是<http://example.com:8080> 傳遞"i am main" 給彈出頁(yè)
// 彈出頁(yè)域名是<http://example.org> 傳遞"i am pop"給主窗口

// 主窗口 JS

var popup = window.open('http://example.org','pop') 
// 參數(shù)是(url,新窗口名稱) 不是title 而是可以用來(lái)作為超鏈接 <a> 或表單 <form> 元素的目標(biāo)屬性值。字符串中不能含有空白字符。

popup.postMessage("i am main", "http://example.org");
// 發(fā)送->  傳遞消息給彈出頁(yè) 第二個(gè)參數(shù)必須精準(zhǔn)匹配

// 接收-> 定義事件處理程序處理接收到的消息
function receiveMessage(event){
    // 必須使用判斷 以保證安全 網(wǎng)站不被攻擊
    if (event.origin !== "http://example.org"){
        return;
    }else{
        // do something
    }
    // event.source 是我們通過(guò)window.open打開(kāi)的彈出頁(yè)面 popup
    // event.data 是 popup發(fā)送給當(dāng)前頁(yè)面的消息
}

window.addEventListener("message",receiveMessage,false)
// 彈出頁(yè) JS
function popReceiveMessage(event){
    if (event.origin !== "http://example.com:8080"){
        return;
    }else{
        // 向來(lái)源窗口發(fā)送回執(zhí)
        event.source.postMessage("i am pop" +event.origin);
    }
}

window.addEventListener("message", popReceiveMessage, false);

二、拖放

拖放事件
  • 發(fā)生在被拖放的元素上。
    • dragstart:按下鼠標(biāo)鍵并開(kāi)始移動(dòng)鼠標(biāo)時(shí)觸發(fā)。
    • drag:在元素被拖動(dòng)期間會(huì)持續(xù)觸發(fā)該事件
    • dragend:當(dāng)拖動(dòng)停止時(shí)觸發(fā)(無(wú)論是否將元素放到了有效目標(biāo))
  • 發(fā)生在放置目標(biāo)上。
    • dragenter:有元素被拖入時(shí)觸發(fā)。
    • dragover:被拖動(dòng)元素在放置目標(biāo)內(nèi)部移動(dòng)時(shí)觸發(fā)。
    • dragleave:被拖動(dòng)元素被拖出放置目標(biāo)后觸發(fā)。(進(jìn)來(lái)之后出去)
    • drop:元素被放到了放置目標(biāo)中時(shí)觸發(fā)。

如果拖動(dòng)元素經(jīng)過(guò)不允許放置的元素,無(wú)論用戶如何操作,都不會(huì)發(fā)生drop 事件。不過(guò),你可以把任何元素變成有效的放置目標(biāo),方法是阻止dragenterdragover 事件的默認(rèn)行為。你就會(huì)發(fā)現(xiàn)當(dāng)拖動(dòng)著元素移動(dòng)到放置目標(biāo)上時(shí),光標(biāo)變成了允許放置的符號(hào)。當(dāng)然,釋放鼠標(biāo)也會(huì)觸發(fā)drop事件。

Firefox 3.5+中,放置事件的默認(rèn)行為是打開(kāi)被放到放置目標(biāo)上的URL(被放入元素是圖片則頁(yè)面轉(zhuǎn)向圖像文件,如果是文本,則導(dǎo)致錯(cuò)誤,無(wú)效的URL),如果想正常處理放置事件,也需要阻止drop事件打開(kāi)URL的行為

dataTransfer對(duì)象

它是事件對(duì)象的一個(gè)屬性,用于從被拖動(dòng)元素向放置目標(biāo)傳遞字符串格式的數(shù)據(jù)。只能在拖放事件的事件處理程序中訪問(wèn)dataTransfer對(duì)象。有兩個(gè)主要方法:getData()setData()

//設(shè)置和接收文本數(shù)據(jù)
event.dataTransfer.setData("text", "some text");
var text = event.dataTransfer.getData("text");
//設(shè)置和接收URL
event.dataTransfer.setData("URL", "http://www.wrox.com/");
var url = event.dataTransfer.getData("URL");

IE只定義了"text""URL"兩種有效的數(shù)據(jù)類型,而HTML5則對(duì)此加以擴(kuò)展,允許指定各種MIME類型。考慮到向后兼容,HTML5 也支持"text""URL",但這兩種類型會(huì)被映射為"text/plain""text/uri-list"。

保存在dataTransfer對(duì)象中的數(shù)據(jù)只能在drop事件處理程序中讀取。如果在ondrop處理程序中沒(méi)有讀到數(shù)據(jù),那就是dataTransfer對(duì)象已經(jīng)被銷毀,數(shù)據(jù)也丟失了。

在拖動(dòng)文本框中的文本或鏈接、圖像時(shí),瀏覽器會(huì)調(diào)用setData()方法以"text""URL"保存,然后,在這些元素被拖放到放置目標(biāo)時(shí),就可以通過(guò)getData()讀到這些數(shù)據(jù)。當(dāng)然,作為開(kāi)發(fā)人員,你也可以在dragstart事件處理程序中調(diào)用setData(),手工保存自己要傳輸?shù)臄?shù)據(jù),以便將來(lái)使用。如果將數(shù)據(jù)保存為URL,瀏覽器會(huì)將其當(dāng)成網(wǎng)頁(yè)中的鏈接。換句話說(shuō),如果你把它放置到另一個(gè)瀏覽器窗口中,瀏覽器就會(huì)打開(kāi)該URL

// 兼容Firefox5之前 不能正確映射"text"和"url" 只能把"Text"(T 大寫(xiě))映射為"text/plain"。 
var dataTransfer = event.dataTransfer;
//讀取URL
var url = dataTransfer.getData("url") ||dataTransfer.getData("text/uri-list");
//讀取文本
var text = dataTransfer.getData("Text");
dataTransfer 對(duì)象的兩個(gè)屬性 dropEffecteffectAllowed
  • dropEffect屬性可以知道被拖動(dòng)的元素能夠執(zhí)行哪種放置行為
    • "none":不能把拖動(dòng)的元素放在這里。這是除文本框之外所有元素的默認(rèn)值。
    • "move":應(yīng)該把拖動(dòng)的元素移動(dòng)到放置目標(biāo)。
    • "copy":應(yīng)該把拖動(dòng)的元素復(fù)制到放置目標(biāo)。
    • "link":表示放置目標(biāo)會(huì)打開(kāi)拖動(dòng)的元素(但拖動(dòng)的元素必須是一個(gè)鏈接,有URL)。

使用dropEffect屬性,必須在ondragenter事件處理程序中針對(duì)放置目標(biāo)來(lái)設(shè)置它。在把元素拖動(dòng)到放置目標(biāo)上時(shí),以上每一個(gè)值都會(huì)導(dǎo)致光標(biāo)顯示為不同的符號(hào)。然而,瀏覽器只能幫你改變光標(biāo)的樣式,而其他的都要靠你自己來(lái)實(shí)現(xiàn)。

dropEffect 屬性只有搭配effectAllowed 屬性才有用。effectAllowed 屬性表示允許拖動(dòng)元素的哪種dropEffect,必須在ondragstart 事件處理程序中設(shè)置effectAllowed 屬性,定義此次拖動(dòng)可以允許哪些操作,而當(dāng)ondragenter觸發(fā)時(shí),針對(duì)放置目標(biāo)來(lái)設(shè)置dropEffect屬性來(lái)進(jìn)行該操作。

  • effectAllowed 屬性表示允許拖動(dòng)元素的哪種dropEffect
    • "uninitialized":沒(méi)有給被拖動(dòng)的元素設(shè)置任何放置行為。
    • "none":被拖動(dòng)的元素不能有任何行為。s
    • "copy":只允許值為"copy"dropEffect
    • "link":只允許值為"link"dropEffect。
    • "move":只允許值為"move"dropEffect
    • "copyLink":允許值為"copy""link"dropEffect。
    • "copyMove":允許值為"copy""move"dropEffect
    • "linkMove":允許值為"link""move"dropEffect。
    • "all":允許任意dropEffect
draggable 可拖動(dòng)

文本在被選中的情況下才能拖動(dòng),而圖像和鏈接在任何時(shí)候都可以拖動(dòng)。HTML5 為所有HTML元素規(guī)定了一個(gè)draggable 屬性,表示元素是否可以拖動(dòng)。圖像和鏈接的draggable 屬性自動(dòng)被設(shè)置成了true,而其他元素這個(gè)屬性的默認(rèn)值都是false。要想讓其他元素可拖動(dòng),或者讓圖像或鏈接不能拖動(dòng),都可以設(shè)置這個(gè)屬性。

其他成員

dataTransfer 對(duì)象還應(yīng)該包含下列方法和屬性

  • addElement(element):為拖動(dòng)操作添加一個(gè)元素。添加這個(gè)元素只影響數(shù)據(jù)(即增加作為拖動(dòng)源而響應(yīng)回調(diào)的對(duì)象),不會(huì)影響拖動(dòng)操作時(shí)頁(yè)面元素的外觀。部分瀏覽器支持
  • clearData(format):清除以特定格式保存的數(shù)據(jù)。實(shí)現(xiàn)這個(gè)方法的瀏覽器有IE、Fireforx 3.5+、ChromeSafari 4+。
  • setDragImage(element, x, y):指定一幅圖像,當(dāng)拖動(dòng)發(fā)生時(shí),顯示在光標(biāo)下方。這個(gè)方法接收的三個(gè)參數(shù)分別是要顯示的HTML元素和光標(biāo)在圖像中的x、y坐標(biāo)。其中,HTML元素可以是一幅圖像,也可以是其他元素。是圖像則顯示圖像,是其他元素則顯示渲染后的元素。實(shí)現(xiàn)這個(gè)方法的瀏覽器有Firefox 3.5+、Safari 4+Chrome。
  • types:當(dāng)前保存的數(shù)據(jù)類型。這是一個(gè)類似數(shù)組的集合,以"text"這樣的字符串形式保存著數(shù)據(jù)類型。實(shí)現(xiàn)這個(gè)屬性的瀏覽器有IE10+、Firefox 3.5+Chrome

三、媒體元素

<audio><video>

位于開(kāi)始和結(jié)束標(biāo)簽之間的任何內(nèi)容都將作為后備內(nèi)容,在瀏覽器不支持這兩個(gè)媒體元素的情況下顯示。因?yàn)椴⒎撬袨g覽器都支持所有媒體格式,所以可以指定多個(gè)不同的媒體來(lái)源。為此,不用在標(biāo)簽中指定src屬性,而是要像下面這樣使用一或多個(gè)<source>元素。

<!-- 嵌入視頻 -->
<video id="myVideo">
    <source src="conference.webm" type="video/webm; codecs='vp8, vorbis'">
    <source src="conference.ogv" type="video/ogg; codecs='theora, vorbis'">
    <source src="conference.mpg">
Video player not available.
</video>

通過(guò)這些屬性可以知道媒體的當(dāng)前狀態(tài)。:

  • src:指向要加載的媒體文件。
  • widthheight:指定視頻播放器的大小
  • poster:屬性指定圖像的URI可以在加載視頻內(nèi)容期間顯示一幅圖像。(封面)
  • controls:布爾值,瀏覽器是否顯示UI 控件,以便用戶直接操作媒體
  • autoplay : 布爾值 取得或設(shè)置autoplay標(biāo)志
  • buffered :時(shí)間范圍 表示已下載的緩沖的時(shí)間范圍的對(duì)象
  • bufferedBytes : 字節(jié)范圍 表示已下載的緩沖的字節(jié)范圍的對(duì)象
  • bufferingRate: 整數(shù) 下載過(guò)程中每秒鐘平均接收到的位數(shù)
  • bufferingThrottled : 布爾值 表示瀏覽器是否對(duì)緩沖進(jìn)行了節(jié)流
  • currentLoop: 整數(shù) 媒體文件已經(jīng)循環(huán)的次數(shù)
  • currentSrc :字符串 當(dāng)前播放的媒體文件的URL
  • currentTime : 浮點(diǎn)數(shù) 已經(jīng)播放的秒數(shù)
  • defaultPlaybackRate :浮點(diǎn)數(shù) 取得或設(shè)置默認(rèn)的播放速度。默認(rèn)值為1.0秒
  • duration :浮點(diǎn)數(shù) 媒體的總播放時(shí)間(秒數(shù))
  • ended : 布爾值 表示媒體文件是否播放完成
  • loop: 布爾值 取得或設(shè)置媒體文件在播放完成后是否再?gòu)念^開(kāi)始播放
  • muted: 布爾值 取得或設(shè)置媒體文件是否靜音
  • networkState: 整數(shù) 表示當(dāng)前媒體的網(wǎng)絡(luò)連接狀態(tài):0表示空,1表示正在加載,2表示正在加載元數(shù)據(jù),3表示已經(jīng)加載了第一幀,4表示加載完成
  • paused: 布爾值 表示播放器是否暫停
  • playbackRate : 浮點(diǎn)數(shù) 取得或設(shè)置當(dāng)前的播放速度。用戶可以改變這個(gè)值,讓媒體播放速度變快或變慢,這與只能由開(kāi)發(fā)人員修改的defaultPlaybackRate不同
  • played: 時(shí)間范圍 到目前為止已經(jīng)播放的時(shí)間范圍
  • readyState :整數(shù) 表示媒體是否已經(jīng)就緒(可以播放了)。0表示數(shù)據(jù)不可用,1表示可以顯示當(dāng)前幀,2表示可以開(kāi)始播放,3表示媒體可以從頭到尾播放
  • seekable : 時(shí)間范圍 可以搜索的時(shí)間范圍
  • seeking: 布爾值 表示播放器是否正移動(dòng)到媒體文件中的新位置
  • start:浮點(diǎn)數(shù) 取得或設(shè)置媒體文件中開(kāi)始播放的位置,以秒表示
  • totalBytes: 整數(shù) 當(dāng)前資源所需的總字節(jié)數(shù)
  • videoHeight: 整數(shù) 返回視頻(不一定是元素)的高度。只適用于<video>
  • videoWidth: 整數(shù) 返回視頻(不一定是元素)的寬度。只適用于<video>
  • volume:浮點(diǎn)數(shù) 取得或設(shè)置當(dāng)前音量,值為0.0到1.0

事件有:

  • abort 下載中斷
  • canplay 可以播放時(shí);readyState值為2
  • canplaythrough: 播放可繼續(xù),而且應(yīng)該不會(huì)中斷;readyState值為3
  • canshowcurrentframe :當(dāng)前幀已經(jīng)下載完成;readyState值為1
  • dataunavailable:因?yàn)闆](méi)有數(shù)據(jù)而不能播放;readyState值為0
  • durationchange :duration屬性的值改變
  • emptied:網(wǎng)絡(luò)連接關(guān)閉
  • empty :發(fā)生錯(cuò)誤阻止了媒體下載
  • ended :媒體已播放到末尾,播放停止
  • error:下載期間發(fā)生網(wǎng)絡(luò)錯(cuò)誤
  • load: 所有媒體已加載完成。這個(gè)事件可能會(huì)被廢棄,建議使用canplaythrough
  • loadeddata:媒體的第一幀已加載完成
  • loadedmetadata: 媒體的元數(shù)據(jù)已加載完成
  • loadstart:下載已開(kāi)始
  • pause: 播放已暫停
  • play: 媒體已接收到指令開(kāi)始播放
  • playing: 媒體已實(shí)際開(kāi)始播放
  • progress: 正在下載
  • ratechange: 播放媒體的速度改變
  • seeked:搜索結(jié)束
  • seeking :正移動(dòng)到新位置
  • stalled 瀏覽器嘗試下載,但未接收到數(shù)據(jù)
  • timeupdatecurrentTime被以不合理或意外的方式更新
  • volumechangevolume屬性值或muted屬性值已改變
  • waiting: 播放暫停,等待下載更多數(shù)據(jù)
//取得元素的引用
var player = document.getElementById("player"),
    btn = document.getElementById("video-btn"),
    curtime = document.getElementById("curtime"),
    duration = document.getElementById("duration");
//更新播放時(shí)間
duration.innerHTML = player.duration;
//為按鈕添加事件處理程序
EventUtil.addHandler(btn, "click", function(event){
    if (player.paused){
        player.play(); // play方法 播放
        btn.value = "Pause";
    } else {
        player.pause(); // pause方法 暫停
        btn.value = "Play";
    }
});
//定時(shí)更新當(dāng)前時(shí)間 以小于1000ms觸發(fā)
setInterval(function(){
    curtime.innerHTML = player.currentTime;
}, 250);
檢測(cè)編解碼器的支持情況

canPlayType()方法,該方法接收一種格式/編解碼器字符串,返回probably"、"maybe"" ",如果給canPlayType()傳入了一種MIME類型(期望接受的是編碼格式字符串),則返回值很可能是"maybe"或空字符串。這是因?yàn)槊襟w文件本身只不過(guò)是音頻或視頻的一個(gè)容器,而真正決定文件能否播放的還是編碼的格式。在同時(shí)傳入MIME類型和編解碼器的情況下,可能性就會(huì)增加,返回的字符串會(huì)變成"probably"。

var audio = document.getElementById("audio-player");
//很可能"maybe"
if (audio.canPlayType("audio/mpeg")){ // MIME
    //進(jìn)一步處理
}
//可能是"probably"
if (audio.canPlayType("audio/ogg; codecs=\"vorbis\"")){ // MIME & 編碼格式
    //進(jìn)一步處理
}

常用音頻的音頻格式和編解碼器

  • AACaudio/mp4; codecs="mp4a.40.2" ,瀏覽器支持的有 IE9+、Safari 4+、iOS版Safari
  • MP3audio/mpeg,瀏覽器支持的有 IE9+、Chrome
  • Vorbisaudio/ogg; codecs="vorbis",瀏覽器支持的有Firefox 3.5+、ChromeOpera 10.5+
  • WAVaudio/wav; codecs="1",瀏覽器支持的有Firefox 3.5+、Opera 10.5+、Chrome

常用視頻的視頻格式和編解碼器

  • H.264video/mp4; codecs="avc1.42E01E, mp4a.40.2" ,瀏覽器支持的有IE9+、Safari 4+、iOS版Safari、Android版WebKit
  • Theoravideo/ogg; codecs="theora",瀏覽器支持的有 Firefox 3.5+、Opera 10.5Chrome
  • WebMvideo/webm; codecs="vp8, vorbis",瀏覽器支持的有Firefox 4+、Opera 10.6、Chrome
Audio類型

<audio>元素還有一個(gè)原生的JavaScript 構(gòu)造函數(shù)Audio,可以在任何時(shí)候播放音頻。從同為DOM元素的角度看,AudioImage很相似,但Audio不用像Image那樣必須插入到文檔中。只要?jiǎng)?chuàng)建一個(gè)新實(shí)例,并傳入音頻源文件即可。

var audio = new Audio("sound.mp3");
EventUtil.addHandler(audio, "canplaythrough", function(event){
    audio.play();
})
// 創(chuàng)建實(shí)例即可開(kāi)始下載指定的文件。下載完成后,調(diào)用play()就可以播放音頻。

iOS 中,調(diào)用play()時(shí)會(huì)彈出一個(gè)對(duì)話框,得到用戶的許可后才能播放聲音。如果想在一段音頻播放后再播放另一段音頻,必須在onfinish事件處理程序中調(diào)用play()方法。

四、歷史狀態(tài)管理

history.pushState()

通過(guò)狀態(tài)管理API, 能夠在不加載新頁(yè)面的情況下改變?yōu)g覽器的URL 。為此, 需要使用history.pushState()方法,該方法可以接收三個(gè)參數(shù):狀態(tài)對(duì)象、新?tīng)顟B(tài)的標(biāo)題和新URL

URL不必須為絕對(duì)路徑。如果新URL是相對(duì)路徑,那么它將被作為相對(duì)于當(dāng)前URL處理。新URL必須與當(dāng)前URL同源,否則 pushState()會(huì)拋出一個(gè)異常。該參數(shù)是可選的,缺省為當(dāng)前URL

// 假設(shè)在 http://mozilla.org/foo.html 中執(zhí)行了以下 JS 代碼:
var stateObj = { foo: "bar" };
history.pushState(stateObj, "page 2", "bar.html");
// 第二個(gè)參數(shù)沒(méi)有瀏覽器實(shí)現(xiàn),可以傳空字符串 或者一個(gè)短標(biāo)題(安全的選擇)。
// 這將使瀏覽器地址欄顯示為 http://mozilla.org/bar.html
// 但并不會(huì)導(dǎo)致瀏覽器加載 bar.html ,甚至不會(huì)檢查bar.html 是否存在。

執(zhí)行pushState()方法后,新的狀態(tài)信息就會(huì)被加入歷史狀態(tài)棧,而瀏覽器地址欄也會(huì)變成新的相對(duì)URL。狀態(tài)改變之后查詢location.href也會(huì)返回與地址欄中相同的地址,但是瀏覽器并不會(huì)真的向服務(wù)器發(fā)送請(qǐng)求。

假設(shè)現(xiàn)在用戶又訪問(wèn)了 http://google.com,然后點(diǎn)擊了返回按鈕。此時(shí),地址欄將顯示 http://mozilla.org/bar.html,同時(shí)頁(yè)面會(huì)觸發(fā) popstate 事件,事件對(duì)象state中包含了 stateObj 的一份拷貝。頁(yè)面本身與 foo.html 一樣,盡管其在 popstate 事件中可能會(huì)修改自身的內(nèi)容。

如果我們?cè)俅吸c(diǎn)擊返回按鈕,頁(yè)面URL會(huì)變?yōu)?code>http://mozilla.org/foo.html,文檔對(duì)象document會(huì)觸發(fā)另外一個(gè) popstate 事件,這一次的事件對(duì)象state objectnull。 這里也一樣,返回并不改變文檔的內(nèi)容,盡管文檔在接收 popstate 事件時(shí)可能會(huì)改變自己的內(nèi)容,其內(nèi)容仍與之前的展現(xiàn)一致

EventUtil.addHandler(window, "popstate", function(event){
    var state = event.state;
    if (state){ //第一個(gè)頁(yè)面加載時(shí)state 為空
        // 進(jìn)一步操作
    }
})
history.replaceState()

history.replaceState()history.pushState()非常相似,區(qū)別在于 replaceState() 是修改(替換)了當(dāng)前的歷史棧棧頂?shù)臓顟B(tài)信息,而不是新增。 注意這并不會(huì)阻止其在全局瀏覽器歷史記錄中創(chuàng)建一個(gè)新的歷史記錄項(xiàng)。

AURL push到 BURL,再push到CURL,后退會(huì)后退到BURL;
AURL push到 BURL,再replace到 CURL,后退會(huì)后退到AURL

popstate事件

每當(dāng)活動(dòng)的歷史記錄項(xiàng)發(fā)生變化時(shí), popstate 事件都會(huì)被傳遞給window對(duì)象。如果當(dāng)前活動(dòng)的歷史記錄項(xiàng)是被 pushState創(chuàng)建的,或者是由 replaceState 改變的,那么 popstate 事件的狀態(tài)屬性 state 會(huì)包含一個(gè)當(dāng)前歷史記錄狀態(tài)對(duì)象的拷貝(調(diào)用這兩個(gè)方法的第一個(gè)參數(shù))

頁(yè)面加載時(shí),或許會(huì)有個(gè)非null的狀態(tài)對(duì)象。這是有可能發(fā)生的,舉個(gè)例子,假如頁(yè)面(通過(guò)pushState()replaceState()方法)設(shè)置了狀態(tài)對(duì)象而后用戶重啟了瀏覽器。那么當(dāng)頁(yè)面重新加載時(shí),頁(yè)面會(huì)接收一個(gè)onload事件,但沒(méi)有popstate事件,但是此時(shí)訪問(wèn)history.state屬性會(huì)得到如同popstate被觸發(fā)時(shí)能得到的狀態(tài)對(duì)象。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 12.3 學(xué)習(xí)了python內(nèi)置模塊turtle,很可愛(ài)的畫(huà)圖模塊 12.4 又開(kāi)始學(xué)習(xí)Tkinter,看文檔的時(shí)...
    橙子樹(shù)上的橙皮猴閱讀 304評(píng)論 0 0
  • *現(xiàn)在我倒是覺(jué)得我處于很危險(xiǎn)的狀態(tài)了,明天考試到現(xiàn)在才讀完兩課罷了,心里充滿了不安!而且我剛剛還在看戲,然后不知道...
    午夜里的街燈閱讀 160評(píng)論 0 1
  • 以秒為單位轉(zhuǎn)換 我們先來(lái)聲明一個(gè)時(shí)間單位是秒的變量,方面下面用 declare @a int = 2000 ---...
    肉肉要次肉閱讀 3,774評(píng)論 0 0
  • 七百年后 已經(jīng)記不清了,上一次這樣靜靜地看著窗外的點(diǎn)點(diǎn)燈光、天上的月亮是什么時(shí)候了。今年暴雨之后便是入伏,天很炎熱...
    貓貓love紅豆粥閱讀 253評(píng)論 1 1

友情鏈接更多精彩內(nèi)容