99re热这里只有精品视频,7777色鬼xxxx欧美色妇,国产成人精品一区二三区在线观看,内射爽无广熟女亚洲,精品人妻av一区二区三区

JavaScript 其他常見事件

2023-03-20 15:46 更新

資源事件 

beforeunload 事件 

beforeunload事件在窗口、文檔、各種資源將要卸載前觸發(fā)。它可以用來防止用戶不小心卸載資源。

如果該事件對象的returnValue屬性是一個非空字符串,那么瀏覽器就會彈出一個對話框,詢問用戶是否要卸載該資源。但是,用戶指定的字符串可能無法顯示,瀏覽器會展示預定義的字符串。如果用戶點擊“取消”按鈕,資源就不會卸載。

window.addEventListener('beforeunload', function (event) {
  event.returnValue = '你確定離開嗎?';
});

上面代碼中,用戶如果關(guān)閉窗口,瀏覽器會彈出一個窗口,要求用戶確認。

瀏覽器對這個事件的行為很不一致,有的瀏覽器調(diào)用event.preventDefault(),也會彈出對話框。IE 瀏覽器需要顯式返回一個非空的字符串,才會彈出對話框。而且,大多數(shù)瀏覽器在對話框中不顯示指定文本,只顯示默認文本。因此,可以采用下面的寫法,取得最大的兼容性。

window.addEventListener('beforeunload', function (e) {
  var confirmationMessage = '確認關(guān)閉窗口?';

  e.returnValue = confirmationMessage;
  return confirmationMessage;
});

注意,許多手機瀏覽器(比如 Safari)默認忽略這個事件,桌面瀏覽器也有辦法忽略這個事件。所以,它可能根本不會生效,不能依賴它來阻止用戶關(guān)閉瀏覽器窗口,最好不要使用這個事件。

另外,一旦使用了beforeunload事件,瀏覽器就不會緩存當前網(wǎng)頁,使用“回退”按鈕將重新向服務(wù)器請求網(wǎng)頁。這是因為監(jiān)聽這個事件的目的,一般是為了網(wǎng)頁狀態(tài),這時緩存頁面的初始狀態(tài)就沒意義了。

unload 事件 

unload事件在窗口關(guān)閉或者document對象將要卸載時觸發(fā)。它的觸發(fā)順序排在beforeunloadpagehide事件后面。

unload事件發(fā)生時,文檔處于一個特殊狀態(tài)。所有資源依然存在,但是對用戶來說都不可見,UI 互動全部無效。這個事件是無法取消的,即使在監(jiān)聽函數(shù)里面拋出錯誤,也不能停止文檔的卸載。

window.addEventListener('unload', function(event) {
  console.log('文檔將要卸載');
});

手機上,瀏覽器或系統(tǒng)可能會直接丟棄網(wǎng)頁,這時該事件根本不會發(fā)生。而且跟beforeunload事件一樣,一旦使用了unload事件,瀏覽器就不會緩存當前網(wǎng)頁,理由同上。因此,任何情況下都不應(yīng)該依賴這個事件,指定網(wǎng)頁卸載時要執(zhí)行的代碼,可以考慮完全不使用這個事件。

該事件可以用pagehide代替。

load 事件,error 事件 

load事件在頁面或某個資源加載成功時觸發(fā)。注意,頁面或資源從瀏覽器緩存加載,并不會觸發(fā)load事件。

window.addEventListener('load', function(event) {
  console.log('所有資源都加載完成');
});

error事件是在頁面或資源加載失敗時觸發(fā)。abort事件在用戶取消加載時觸發(fā)。

這三個事件實際上屬于進度事件,不僅發(fā)生在document對象,還發(fā)生在各種外部資源上面。瀏覽網(wǎng)頁就是一個加載各種資源的過程,圖像(image)、樣式表(style sheet)、腳本(script)、視頻(video)、音頻(audio)、Ajax請求(XMLHttpRequest)等等。這些資源和document對象、window對象、XMLHttpRequestUpload 對象,都會觸發(fā)load事件和error事件。

最后,頁面的load事件也可以用pageshow事件代替。

session 歷史事件 

pageshow 事件,pagehide 事件 

默認情況下,瀏覽器會在當前會話(session)緩存頁面,當用戶點擊“前進/后退”按鈕時,瀏覽器就會從緩存中加載頁面。

pageshow事件在頁面加載時觸發(fā),包括第一次加載和從緩存加載兩種情況。如果要指定頁面每次加載(不管是不是從瀏覽器緩存)時都運行的代碼,可以放在這個事件的監(jiān)聽函數(shù)。

第一次加載時,它的觸發(fā)順序排在load事件后面。從緩存加載時,load事件不會觸發(fā),因為網(wǎng)頁在緩存中的樣子通常是load事件的監(jiān)聽函數(shù)運行后的樣子,所以不必重復執(zhí)行。同理,如果是從緩存中加載頁面,網(wǎng)頁內(nèi)初始化的 JavaScript 腳本(比如 DOMContentLoaded 事件的監(jiān)聽函數(shù))也不會執(zhí)行。

window.addEventListener('pageshow', function(event) {
  console.log('pageshow: ', event);
});

pageshow事件有一個persisted屬性,返回一個布爾值。頁面第一次加載時,這個屬性是false;當頁面從緩存加載時,這個屬性是true。

window.addEventListener('pageshow', function(event){
  if (event.persisted) {
    // ...
  }
});

pagehide事件與pageshow事件類似,當用戶通過“前進/后退”按鈕,離開當前頁面時觸發(fā)。它與 unload 事件的區(qū)別在于,如果在 window 對象上定義unload事件的監(jiān)聽函數(shù)之后,頁面不會保存在緩存中,而使用pagehide事件,頁面會保存在緩存中。

pagehide事件實例也有一個persisted屬性,將這個屬性設(shè)為true,就表示頁面要保存在緩存中;設(shè)為false,表示網(wǎng)頁不保存在緩存中,這時如果設(shè)置了unload 事件的監(jiān)聽函數(shù),該函數(shù)將在 pagehide 事件后立即運行。

如果頁面包含<frame><iframe>元素,則<frame>頁面的pageshow事件和pagehide事件,都會在主頁面之前觸發(fā)。

注意,這兩個事件只在瀏覽器的history對象發(fā)生變化時觸發(fā),跟網(wǎng)頁是否可見沒有關(guān)系。

popstate 事件 

popstate事件在瀏覽器的history對象的當前記錄發(fā)生顯式切換時觸發(fā)。注意,調(diào)用history.pushState()history.replaceState(),并不會觸發(fā)popstate事件。該事件只在用戶在history記錄之間顯式切換時觸發(fā),比如鼠標點擊“后退/前進”按鈕,或者在腳本中調(diào)用history.back()、history.forward()、history.go()時觸發(fā)。

該事件對象有一個state屬性,保存history.pushState方法和history.replaceState方法為當前記錄添加的state對象。

window.onpopstate = function (event) {
  console.log('state: ' + event.state);
};
history.pushState({page: 1}, 'title 1', '?page=1');
history.pushState({page: 2}, 'title 2', '?page=2');
history.replaceState({page: 3}, 'title 3', '?page=3');
history.back(); // state: {"page":1}
history.back(); // state: null
history.go(2);  // state: {"page":3}

上面代碼中,pushState方法向history添加了兩條記錄,然后replaceState方法替換掉當前記錄。因此,連續(xù)兩次back方法,會讓當前條目退回到原始網(wǎng)址,它沒有附帶state對象,所以事件的state屬性為null,然后前進兩條記錄,又回到replaceState方法添加的記錄。

瀏覽器對于頁面首次加載,是否觸發(fā)popstate事件,處理不一樣,F(xiàn)irefox 不觸發(fā)該事件。

hashchange 事件 

hashchange事件在 URL 的 hash 部分(即#號后面的部分,包括#號)發(fā)生變化時觸發(fā)。該事件一般在window對象上監(jiān)聽。

hashchange的事件實例具有兩個特有屬性:oldURL屬性和newURL屬性,分別表示變化前后的完整 URL。

// URL 是 http://www.example.com/
window.addEventListener('hashchange', myFunction);

function myFunction(e) {
  console.log(e.oldURL);
  console.log(e.newURL);
}

location.hash = 'part2';
// http://www.example.com/
// http://www.example.com/#part2

網(wǎng)頁狀態(tài)事件 

DOMContentLoaded 事件 

網(wǎng)頁下載并解析完成以后,瀏覽器就會在document對象上觸發(fā) DOMContentLoaded 事件。這時,僅僅完成了網(wǎng)頁的解析(整張頁面的 DOM 生成了),所有外部資源(樣式表、腳本、iframe 等等)可能還沒有下載結(jié)束。也就是說,這個事件比load事件,發(fā)生時間早得多。

document.addEventListener('DOMContentLoaded', function (event) {
  console.log('DOM生成');
});

注意,網(wǎng)頁的 JavaScript 腳本是同步執(zhí)行的,腳本一旦發(fā)生堵塞,將推遲觸發(fā)DOMContentLoaded事件。

document.addEventListener('DOMContentLoaded', function (event) {
  console.log('DOM 生成');
});

// 這段代碼會推遲觸發(fā) DOMContentLoaded 事件
for(var i = 0; i < 1000000000; i++) {
  // ...
}

readystatechange 事件 

readystatechange事件當 Document 對象和 XMLHttpRequest 對象的readyState屬性發(fā)生變化時觸發(fā)。document.readyState有三個可能的值:loading(網(wǎng)頁正在加載)、interactive(網(wǎng)頁已經(jīng)解析完成,但是外部資源仍然處在加載狀態(tài))和complete(網(wǎng)頁和所有外部資源已經(jīng)結(jié)束加載,load事件即將觸發(fā))。

document.onreadystatechange = function () {
  if (document.readyState === 'interactive') {
    // ...
  }
}

這個事件可以看作DOMContentLoaded事件的另一種實現(xiàn)方法。

窗口事件 

scroll 事件 

scroll事件在文檔或文檔元素滾動時觸發(fā),主要出現(xiàn)在用戶拖動滾動條。

window.addEventListener('scroll', callback);

該事件會連續(xù)地大量觸發(fā),所以它的監(jiān)聽函數(shù)之中不應(yīng)該有非常耗費計算的操作。推薦的做法是使用requestAnimationFramesetTimeout控制該事件的觸發(fā)頻率,然后可以結(jié)合customEvent拋出一個新事件。

(function () {
  var throttle = function (type, name, obj) {
    var obj = obj || window;
    var running = false;
    var func = function () {
      if (running) { return; }
      running = true;
      requestAnimationFrame(function() {
        obj.dispatchEvent(new CustomEvent(name));
        running = false;
      });
    };
    obj.addEventListener(type, func);
  };

  // 將 scroll 事件轉(zhuǎn)為 optimizedScroll 事件
  throttle('scroll', 'optimizedScroll');
})();

window.addEventListener('optimizedScroll', function() {
  console.log('Resource conscious scroll callback!');
});

上面代碼中,throttle()函數(shù)用于控制事件觸發(fā)頻率,它有一個內(nèi)部函數(shù)func(),每次scroll事件實際上觸發(fā)的是這個函數(shù)。func()函數(shù)內(nèi)部使用requestAnimationFrame()方法,保證只有每次頁面重繪時(每秒60次),才可能會觸發(fā)optimizedScroll事件,從而實際上將scroll事件轉(zhuǎn)換為optimizedScroll事件,觸發(fā)頻率被控制在每秒最多60次。

改用setTimeout()方法,可以放置更大的時間間隔。

(function() {
  window.addEventListener('scroll', scrollThrottler, false);

  var scrollTimeout;
  function scrollThrottler() {
    if (!scrollTimeout) {
      scrollTimeout = setTimeout(function () {
        scrollTimeout = null;
        actualScrollHandler();
      }, 66);
    }
  }

  function actualScrollHandler() {
    // ...
  }
}());

上面代碼中,每次scroll事件都會執(zhí)行scrollThrottler函數(shù)。該函數(shù)里面有一個定時器setTimeout,每66毫秒觸發(fā)一次(每秒15次)真正執(zhí)行的任務(wù)actualScrollHandler。

下面是一個更一般的throttle函數(shù)的寫法。

function throttle(fn, wait) {
  var time = Date.now();
  return function() {
    if ((time + wait - Date.now()) < 0) {
      fn();
      time = Date.now();
    }
  }
}

window.addEventListener('scroll', throttle(callback, 1000));

上面的代碼將scroll事件的觸發(fā)頻率,限制在一秒一次。

lodash函數(shù)庫提供了現(xiàn)成的throttle函數(shù),可以直接使用。

window.addEventListener('scroll', _.throttle(callback, 1000));

本書前面介紹過debounce的概念,throttle與它區(qū)別在于,throttle是“節(jié)流”,確保一段時間內(nèi)只執(zhí)行一次,而debounce是“防抖”,要連續(xù)操作結(jié)束后再執(zhí)行。以網(wǎng)頁滾動為例,debounce要等到用戶停止?jié)L動后才執(zhí)行,throttle則是如果用戶一直在滾動網(wǎng)頁,那么在滾動過程中還是會執(zhí)行。

resize 事件 

resize事件在改變?yōu)g覽器窗口大小時觸發(fā),主要發(fā)生在window對象上面。

var resizeMethod = function () {
  if (document.body.clientWidth < 768) {
    console.log('移動設(shè)備的視口');
  }
};

window.addEventListener('resize', resizeMethod, true);

該事件也會連續(xù)地大量觸發(fā),所以最好像上面的scroll事件一樣,通過throttle函數(shù)控制事件觸發(fā)頻率。

fullscreenchange 事件,fullscreenerror 事件 

fullscreenchange事件在進入或退出全屏狀態(tài)時觸發(fā),該事件發(fā)生在document對象上面。

document.addEventListener('fullscreenchange', function (event) {
  console.log(document.fullscreenElement);
});

fullscreenerror事件在瀏覽器無法切換到全屏狀態(tài)時觸發(fā)。

剪貼板事件 

以下三個事件屬于剪貼板操作的相關(guān)事件。

  • cut:將選中的內(nèi)容從文檔中移除,加入剪貼板時觸發(fā)。
  • copy:進行復制動作時觸發(fā)。
  • paste:剪貼板內(nèi)容粘貼到文檔后觸發(fā)。

舉例來說,如果希望禁止輸入框的粘貼事件,可以使用下面的代碼。

inputElement.addEventListener('paste', e => e.preventDefault());

上面的代碼使得用戶無法在<input>輸入框里面粘貼內(nèi)容。

cutcopy、paste這三個事件的事件對象都是ClipboardEvent接口的實例。ClipboardEvent有一個實例屬性clipboardData,是一個 DataTransfer 對象,存放剪貼的數(shù)據(jù)。具體的 API 接口和操作方法,請參見《拖拉事件》的 DataTransfer 對象部分。

document.addEventListener('copy', function (e) {
  e.clipboardData.setData('text/plain', 'Hello, world!');
  e.clipboardData.setData('text/html', '<b>Hello, world!</b>');
  e.preventDefault();
});

上面的代碼使得復制進入剪貼板的,都是開發(fā)者指定的數(shù)據(jù),而不是用戶想要拷貝的數(shù)據(jù)。

焦點事件 

焦點事件發(fā)生在元素節(jié)點和document對象上面,與獲得或失去焦點相關(guān)。它主要包括以下四個事件。

  • focus:元素節(jié)點獲得焦點后觸發(fā),該事件不會冒泡。
  • blur:元素節(jié)點失去焦點后觸發(fā),該事件不會冒泡。
  • focusin:元素節(jié)點將要獲得焦點時觸發(fā),發(fā)生在focus事件之前。該事件會冒泡。
  • focusout:元素節(jié)點將要失去焦點時觸發(fā),發(fā)生在blur事件之前。該事件會冒泡。

這四個事件的事件對象都繼承了FocusEvent接口。FocusEvent實例具有以下屬性。

  • FocusEvent.target:事件的目標節(jié)點。
  • FocusEvent.relatedTarget:對于focusin事件,返回失去焦點的節(jié)點;對于focusout事件,返回將要接受焦點的節(jié)點;對于focusblur事件,返回null。

由于focusblur事件不會冒泡,只能在捕獲階段觸發(fā),所以addEventListener方法的第三個參數(shù)需要設(shè)為true。

form.addEventListener('focus', function (event) {
  event.target.style.background = 'pink';
}, true);

form.addEventListener('blur', function (event) {
  event.target.style.background = '';
}, true);

上面代碼針對表單的文本輸入框,接受焦點時設(shè)置背景色,失去焦點時去除背景色。

CustomEvent 接口 

CustomEvent 接口用于生成自定義的事件實例。那些瀏覽器預定義的事件,雖然可以手動生成,但是往往不能在事件上綁定數(shù)據(jù)。如果需要在觸發(fā)事件的同時,傳入指定的數(shù)據(jù),就可以使用 CustomEvent 接口生成的自定義事件對象。

瀏覽器原生提供CustomEvent()構(gòu)造函數(shù),用來生成 CustomEvent 事件實例。

new CustomEvent(type, options)

CustomEvent()構(gòu)造函數(shù)接受兩個參數(shù)。第一個參數(shù)是字符串,表示事件的名字,這是必須的。第二個參數(shù)是事件的配置對象,這個參數(shù)是可選的。CustomEvent的配置對象除了接受 Event 事件的配置屬性,只有一個自己的屬性。

  • detail:表示事件的附帶數(shù)據(jù),默認為null。

下面是一個例子。

var event = new CustomEvent('build', { 'detail': 'hello' });

function eventHandler(e) {
  console.log(e.detail);
}

document.body.addEventListener('build', function (e) {
  console.log(e.detail);
});

document.body.dispatchEvent(event);

上面代碼中,我們手動定義了build事件。該事件觸發(fā)后,會被監(jiān)聽到,從而輸出該事件實例的detail屬性(即字符串hello)。

下面是另一個例子。

var myEvent = new CustomEvent('myevent', {
  detail: {
    foo: 'bar'
  },
  bubbles: true,
  cancelable: false
});

el.addEventListener('myevent', function (event) {
  console.log('Hello ' + event.detail.foo);
});

el.dispatchEvent(myEvent);

上面代碼也說明,CustomEvent 的事件實例,除了具有 Event 接口的實例屬性,還具有detail屬性。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號