節(jié)流函數(shù)是防止短時(shí)間內(nèi)多次觸發(fā)的一個(gè)處理函數(shù)
如:滾動(dòng)事件溃卡,使用 addEventListener 方式添加監(jiān)聽器
window.addEventListener( "scroll",
throttle(
() => {
const scrollTop = window.scrollY;
// dosomething
}
)
)
function throttle(action, wait=1000) {
let time = Date.now()
return function () {
if (time + wait - Date.now() < 0) {
action();
time = Date.now()
}
}
}
為了使節(jié)流之后滾動(dòng)更加的平滑烂翰, 我們可以使用 window.requestAnimationFrame() 來實(shí)現(xiàn)節(jié)流函數(shù)
function throttle (action){
let call = false;
return function () {
call = true;
window.requestAnimationFrame(
() => {
action()
call = false
}
)
}
}
在視窗中顯示
當(dāng)需要實(shí)現(xiàn)圖片的懶加載或者是無限滾動(dòng)時(shí),需要確定元素是否出現(xiàn)在視窗中休溶, 這樣需要獲取 elem.getBoundingClientRect();
window.addEventListener ( "scroll", () => {
const {bottom, right, left, top} = elem.getBoundingClientRect();
const inViewport = bottom > 0 && right > 0 && left < window.innerWidth && top < window.innerHeight;
注意: 每次調(diào)用 getBoundingClientRect 時(shí)都會(huì)觸發(fā)回流代赁, 這樣會(huì)嚴(yán)重的影響性能,特別是在事件處理函數(shù)中兽掰,會(huì)更加的嚴(yán)重影響性能芭碍;
在 2016 年之后, 可以通過 Intersection Observer 這個(gè) api 來解決問題孽尽, 它允許你追蹤目標(biāo)元素與其祖先元素或者視窗的交叉狀態(tài)窖壕, 另外只有一部分元素出現(xiàn)在視窗中,哪怕只有 1 px 杉女, 也可以選擇觸發(fā)回調(diào)函數(shù)
const observer = new IntersectionObserver (callback瞻讽, options);
observer.observe(element);
滾動(dòng)邊界的問題:
當(dāng)用戶滾到末尾時(shí)熏挎, 整個(gè)頁面都會(huì)開始滾動(dòng)速勇;
連鎖滾動(dòng)的表現(xiàn), 當(dāng)滾動(dòng)有婆瓜;元素到達(dá)底部時(shí)快集,可以改變頁面的 overflow 屬性或者在滾動(dòng)元素的滾動(dòng)事件處理函數(shù)中取消默認(rèn)行為來解決這個(gè)問題
如果使用 JavaScript 處理, 那么處理的不是 scroll 事件廉白, 而是每當(dāng)用戶使用鼠標(biāo)滾輪 或者 是觸摸板時(shí) 觸發(fā)的是 wheel 事件
過度滾動(dòng)對(duì)移動(dòng)端的影響尤為的嚴(yán)重个初,下拉刷新的手勢(shì)在 安卓的chrome 瀏覽器中,問題出現(xiàn)了猴蹂,它會(huì)刷新整個(gè)頁面榜苫, 而不是加載更多的內(nèi)容碑隆;這個(gè)就會(huì)產(chǎn)生很多問題;
css 通過 overscroll-behavior 這個(gè)新屬性解決問題渔彰。它通過控制元素滾動(dòng)到盡頭時(shí)的行為來解決 下拉刷新與 連鎖滾動(dòng)帶來的問題。安卓的 glow 與蘋果中的 rubber band嫡秕。
.element {
overscroll-vehavior: contain;
}
準(zhǔn)確的說, IE 與 Edge 實(shí)現(xiàn)了獨(dú)有的 -ms-scroll-chaining 屬性來控制連鎖滾動(dòng);
微軟瀏覽器已經(jīng)準(zhǔn)備實(shí)現(xiàn) overscroll-behavior 這個(gè)屬性
觸屏之后
在觸屏設(shè)備上叭爱,滾動(dòng)的體驗(yàn)是一個(gè)很大的話題。
蘋果公司開發(fā)了 慣性 滾動(dòng)的專利漱病;
css 有一個(gè)很hack 的方法买雾;
.element {
-webkit-overflow-scrolling: touch;
}
只支持 webkit 內(nèi)核,
但是我們會(huì)使用 touch 事件來解決這個(gè)問題杨帽,但是這個(gè)會(huì)對(duì)用戶滾動(dòng)體驗(yàn)造成很大的影響漓穿;
在現(xiàn)代的瀏覽器中,雖然知道如何使?jié)L動(dòng)變得平滑注盈,但為了 確定滾動(dòng)事件處理函數(shù)中是否執(zhí)行了 阻止默認(rèn)事件 晃危;可能任會(huì)花費(fèi) 500 mm 來等待事件處理函數(shù)執(zhí)行完畢
即使是一個(gè)空的事件監(jiān)聽函數(shù), 從不取消任何行為老客,鑒于瀏覽器會(huì)期待 preventDefault 的調(diào)用僚饭, 也會(huì)對(duì)性能造成影響
為了告訴瀏覽器不去檢測(cè)事件是否阻止了默認(rèn)事件,在 whatwg dom 標(biāo)準(zhǔn)中沿量,存在一個(gè)特性浪慌,來解決這個(gè)事件,
elem.addEventListener('event', e => {
dosomething
}, {passive: true }
)
這個(gè)視頻會(huì)看到帶來的性能提升: https://www.youtube.com/watch?v=NPM6172J22g