使用JavaScript實(shí)現(xiàn)檢測(cè)網(wǎng)頁(yè)是否為空閑狀態(tài)
1. 背景
最近開(kāi)發(fā)項(xiàng)目時(shí),常碰到“用戶在一定時(shí)間內(nèi)無(wú)任何操作時(shí),跳轉(zhuǎn)到某個(gè)頁(yè)面”的需求。
網(wǎng)上沖浪后,也沒(méi)有找到一個(gè)比較好的js封裝去解決這個(gè)問(wèn)題,從而決定自己實(shí)現(xiàn)。
2. 如何判斷頁(yè)面是否空閑(用戶長(zhǎng)時(shí)間無(wú)操作)
首先,我們要知道什么是空閑?用戶一定時(shí)間內(nèi),沒(méi)有對(duì)網(wǎng)頁(yè)進(jìn)行任何操作,則當(dāng)前網(wǎng)頁(yè)為空閑狀態(tài)。
用戶操作網(wǎng)頁(yè),無(wú)非就是通過(guò)鼠標(biāo)
、鍵盤
兩個(gè)輸入設(shè)備(暫不考慮手柄等設(shè)備)。因而我們可以監(jiān)聽(tīng)相應(yīng)的輸入事件,來(lái)判斷網(wǎng)頁(yè)是否空閑(用戶是否操作網(wǎng)頁(yè))。
- 監(jiān)聽(tīng)鼠標(biāo)移動(dòng)事件
mousemove
; - 監(jiān)聽(tīng)鍵盤按下事件
mousedown
; - 在用戶進(jìn)入網(wǎng)頁(yè)后,設(shè)置延時(shí)跳轉(zhuǎn),如果觸發(fā)以上事件,則移除延時(shí)器,并重新開(kāi)始。
3. 網(wǎng)頁(yè)空閑檢測(cè)實(shí)現(xiàn)
3.1 簡(jiǎn)易實(shí)現(xiàn)
以下代碼,簡(jiǎn)易實(shí)現(xiàn)了一個(gè)判斷網(wǎng)頁(yè)空閑的方法。
const onIdleDetection = (callback, timeout = 15, immediate = false) => { let pageTimer; const onClearTimer = () => { pageTimer && clearTimeout(pageTimer); pageTimer = undefined; }; const onStartTimer = () => { onClearTimer(); pageTimer = setTimeout(() => { callback(); }, timeout * 1000); }; const startDetection = () => { onStartTimer(); document.addEventListener('mousedown', onStartTimer); document.addEventListener('mousemove', onStartTimer); }; const stopDetection = () => { onClearTimer(); document.removeEventListener('mousedown', onStartTimer); document.removeEventListener('mousemove', onStartTimer); }; const restartDetection = () => { onClearTimer(); onStartTimer(); }; if (immediate) { startDetection(); } return { startDetection, stopDetection, restartDetection }; };
也許你注意到了,我并沒(méi)有針對(duì)onStartTimer
事件進(jìn)行防抖,那這是不是會(huì)對(duì)性能有影響呢?
是的,肯定有那么點(diǎn)影響,那我為啥不添加防抖呢?
這是因?yàn)樘砑臃蓝逗?,形成?code>setTimeout嵌套,嵌套setTimeout
會(huì)有精度問(wèn)題(參考)。
或許你還會(huì)說(shuō),非活動(dòng)標(biāo)簽頁(yè)(網(wǎng)頁(yè)被隱藏)的setTimeout
的執(zhí)行和精度會(huì)有問(wèn)題(參考非活動(dòng)標(biāo)簽的超時(shí))。
確實(shí)存在以上問(wèn)題,接下來(lái)我們就來(lái)一一解決吧!
3.2 處理頻繁觸發(fā)問(wèn)題
我們可以通過(guò)添加一個(gè)變量記錄開(kāi)始執(zhí)行時(shí)間,當(dāng)下一次執(zhí)行與當(dāng)前的時(shí)間間隔小于某個(gè)值時(shí)直接退出函數(shù),從而解決這個(gè)問(wèn)題(節(jié)流思想應(yīng)用)。
const onIdleDetection = (callback, timeout = 15, immediate = false) => { let pageTimer; // 記錄開(kāi)始時(shí)間 let beginTime = 0; const onStartTimer = () => { // 觸發(fā)間隔小于100ms時(shí),直接返回 const currentTime = Date.now(); if (pageTimer && currentTime - beginTime < 100) { return; } onClearTimer(); // 更新開(kāi)始時(shí)間 beginTime = currentTime; pageTimer = setTimeout(() => { callback(); }, timeout * 1000); }; const onClearTimer = () => { pageTimer && clearTimeout(pageTimer); pageTimer = undefined; }; const startDetection = () => { onStartTimer(); document.addEventListener('mousedown', onStartTimer); document.addEventListener('mousemove', onStartTimer); }; const stopDetection = () => { onClearTimer(); document.removeEventListener('mousedown', onStartTimer); document.removeEventListener('mousemove', onStartTimer); }; const restartDetection = () => { onClearTimer(); onStartTimer(); }; if (immediate) { startDetection(); } return { startDetection, stopDetection, restartDetection }; };
3.3 處理頁(yè)面被隱藏的情況(完整實(shí)現(xiàn))
我們可以監(jiān)聽(tīng)visibilitychange
事件,在頁(yè)面隱藏時(shí)移除延時(shí)器,然后頁(yè)面顯示時(shí)繼續(xù)計(jì)時(shí),從而解決這個(gè)問(wèn)題。
/** * 網(wǎng)頁(yè)空閑檢測(cè) * @param {() => void} callback 空閑時(shí)執(zhí)行,即一定時(shí)長(zhǎng)無(wú)操作時(shí)觸發(fā) * @param {number} [timeout=15] 時(shí)長(zhǎng),默認(rèn)15s,單位:秒 * @param {boolean} [immediate=false] 是否立即開(kāi)始,默認(rèn) false * @returns */ const onIdleDetection = (callback, timeout = 15, immediate = false) => { let pageTimer; let beginTime = 0; const onClearTimer = () => { pageTimer && clearTimeout(pageTimer); pageTimer = undefined; }; const onStartTimer = () => { const currentTime = Date.now(); if (pageTimer && currentTime - beginTime < 100) { return; } onClearTimer(); beginTime = currentTime; pageTimer = setTimeout(() => { callback(); }, timeout * 1000); }; const onPageVisibility = () => { // 頁(yè)面顯示狀態(tài)改變時(shí),移除延時(shí)器 onClearTimer(); if (document.visibilityState === 'visible') { const currentTime = Date.now(); // 頁(yè)面顯示時(shí),計(jì)算時(shí)間,如果超出限制時(shí)間則直接執(zhí)行回調(diào)函數(shù) if (currentTime - beginTime >= timeout * 1000) { callback(); return; } // 繼續(xù)計(jì)時(shí) pageTimer = setTimeout(() => { callback(); }, timeout * 1000 - (currentTime - beginTime)); } }; const startDetection = () => { onStartTimer(); document.addEventListener('mousedown', onStartTimer); document.addEventListener('mousemove', onStartTimer); document.addEventListener('visibilitychange', onPageVisibility); }; const stopDetection = () => { onClearTimer(); document.removeEventListener('mousedown', onStartTimer); document.removeEventListener('mousemove', onStartTimer); document.removeEventListener('visibilitychange', onPageVisibility); }; const restartDetection = () => { onClearTimer(); onStartTimer(); }; if (immediate) { startDetection(); } return { startDetection, stopDetection, restartDetection }; };
通過(guò)以上代碼,我們就完整地實(shí)現(xiàn)了一個(gè)網(wǎng)頁(yè)空閑狀態(tài)檢測(cè)的方法。
4. 擴(kuò)展
chrome瀏覽器其實(shí)提供了一個(gè)Idle Detection
API,來(lái)實(shí)現(xiàn)網(wǎng)頁(yè)空閑狀態(tài)的檢測(cè),但是這個(gè)API還是一個(gè)實(shí)驗(yàn)性特性,并且Firefox與Safari不支持。API參考
到此這篇關(guān)于使用JavaScript實(shí)現(xiàn)檢測(cè)網(wǎng)頁(yè)是否為空閑狀態(tài)的文章就介紹到這了,更多相關(guān)JavaScript檢測(cè)網(wǎng)頁(yè)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 基于javascript代碼檢測(cè)訪問(wèn)網(wǎng)頁(yè)的瀏覽器呈現(xiàn)引擎、平臺(tái)、Windows操作系統(tǒng)、移動(dòng)設(shè)備和游戲系統(tǒng)
- js實(shí)現(xiàn)網(wǎng)頁(yè)檢測(cè)是否安裝了 Flash Player 插件
- Javascript檢查圖片大小不要讓大圖片撐破頁(yè)面
- JavaScript實(shí)現(xiàn)檢查頁(yè)面上的廣告是否被AdBlock屏蔽了的方法
- js檢查頁(yè)面上有無(wú)重復(fù)id的實(shí)現(xiàn)代碼
- javascript檢測(cè)頁(yè)面是否縮放的小例子
相關(guān)文章
JavaScript操作select元素和option的實(shí)例代碼
這篇文章主要介紹了JavaScript操作select元素和option的實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2016-01-01js獲取url中的參數(shù)且參數(shù)為中文時(shí)通過(guò)js解碼
這篇文章主要介紹了url中傳遞中文參數(shù)的時(shí)候通過(guò)js解碼,需要的朋友可以參考下2014-03-03JS生成不重復(fù)的隨機(jī)數(shù)組的簡(jiǎn)單實(shí)例
下面小編就為大家?guī)?lái)一篇JS生成不重復(fù)的隨機(jī)數(shù)組的簡(jiǎn)單實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-07-07微信小程序?qū)崿F(xiàn)animation動(dòng)畫
這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)animation動(dòng)畫的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01微信小程序開(kāi)發(fā)之a(chǎn)nimation循環(huán)動(dòng)畫實(shí)現(xiàn)的讓云朵飄效果
這篇文章主要介紹了微信小程序開(kāi)發(fā)之a(chǎn)nimation循環(huán)動(dòng)畫實(shí)現(xiàn)的讓云朵飄效果,結(jié)合實(shí)例形式分析了animation結(jié)合js時(shí)間函數(shù)實(shí)現(xiàn)循環(huán)動(dòng)畫效果的具體步驟與相關(guān)操作技巧,需要的朋友可以參考下2017-07-07Echarts?graph關(guān)系圖的使用入門級(jí)教程
近期需要使用echarts關(guān)系圖,這里給大家總結(jié)下,這篇文章主要給大家介紹了關(guān)于Echarts?graph關(guān)系圖使用的相關(guān)資料,文中給出了詳細(xì)的代碼介紹,需要的朋友可以參考下2024-01-01Javascript HTML5 Canvas實(shí)現(xiàn)的一個(gè)畫板
這篇文章主要為大家詳細(xì)介紹了Javascript HTML5 Canvas實(shí)現(xiàn)的一個(gè)畫板的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-05-05深入理解JavaScript字節(jié)二進(jìn)制知識(shí)以及相關(guān)API
當(dāng)前,前端對(duì)二進(jìn)制數(shù)據(jù)有許多的API可以使用,這豐富了前端對(duì)文件數(shù)據(jù)的處理能力,有了這些能力,就能夠?qū)D片等文件的數(shù)據(jù)進(jìn)行各種處理。本文將著重介紹一些前端二進(jìn)制數(shù)據(jù)處理相關(guān)的API知識(shí),希望對(duì)大家有所幫助2023-02-02JavaScript中 this 指向問(wèn)題深度解析
這篇文章主要介紹了JavaScript中 this 指向問(wèn)題深度解析,JavaScript 中的 this 指向問(wèn)題有很多文章在解釋,仍然有很多人問(wèn),本文給大家深度解析,需要的朋友可以參考下2017-02-02JS克隆,屬性,數(shù)組,對(duì)象,函數(shù)實(shí)例分析
這篇文章主要介紹了JS克隆,屬性,數(shù)組,對(duì)象,函數(shù),結(jié)合實(shí)例形式分析了javascript中面向?qū)ο蟪绦蛟O(shè)計(jì)相關(guān)的對(duì)象、屬性、函數(shù)及數(shù)組等相關(guān)技巧,需要的朋友可以參考下2016-11-11