溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

如何使用ES6寫(xiě)全屏滾動(dòng)插件

發(fā)布時(shí)間:2021-07-22 14:41:05 來(lái)源:億速云 閱讀:135 作者:小新 欄目:web開(kāi)發(fā)

這篇文章主要為大家展示了“如何使用ES6寫(xiě)全屏滾動(dòng)插件”,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“如何使用ES6寫(xiě)全屏滾動(dòng)插件”這篇文章吧。

1)前面的話(huà)

現(xiàn)在已經(jīng)有很多全屏滾動(dòng)插件了,比如著名的 fullPage ,那為什么還要自己造輪子呢?

現(xiàn)有輪子有以下問(wèn)題:

  1. 首先,最大的問(wèn)題是最流行的幾個(gè)插件都依賴(lài) jQuery,這意味著在使用 React 或者 Vue 的項(xiàng)目中使用他們是一件十分蛋疼的事:我只需要一個(gè)全屏滾動(dòng)功能,卻還需要把 jQuery 引入,有種殺雞使用宰牛刀的感覺(jué);

  2. 其次,現(xiàn)有的很多全屏滾動(dòng)插件功能往往都十分豐富,這在前幾年是優(yōu)勢(shì),但現(xiàn)在(2018-5)可以看作是劣勢(shì):前端開(kāi)發(fā)已經(jīng)發(fā)生了很大變化,其中很重要的一個(gè)變化是 ES6 原生支持模塊化開(kāi)發(fā),模塊化開(kāi)發(fā)最大的特點(diǎn)是一個(gè)模塊最好只專(zhuān)注做好一件事,然后再拼成一個(gè)完整的系統(tǒng),從這個(gè)角度看,大而全的插件有悖模塊化開(kāi)發(fā)的原則。

對(duì)比之下,通過(guò)原生語(yǔ)言造輪子有以下好處:

  1. 使用原生語(yǔ)言編寫(xiě)的插件,自身不會(huì)受依賴(lài)的插件的使用場(chǎng)景而影響自身的使用(現(xiàn)在依賴(lài) jQuery 的插件非常不適合開(kāi)發(fā)單頁(yè)面應(yīng)用),所以使用上更加靈活;

  2. 搭配模塊化開(kāi)發(fā),使用原生語(yǔ)言開(kāi)發(fā)的插件可以只專(zhuān)注一個(gè)功能,所以代碼量可以很少;

  3. 最后,隨著 JS/CSS/HTML 的發(fā)展以及瀏覽器不斷迭代更新,現(xiàn)在使用原生語(yǔ)言編寫(xiě)插件的開(kāi)發(fā)成本越來(lái)越低,那為什么不呢?

2)實(shí)現(xiàn)原理及代碼架構(gòu)

2.1 實(shí)現(xiàn)原理

實(shí)現(xiàn)原理見(jiàn)下圖:容器及容器內(nèi)的頁(yè)面取當(dāng)前可視區(qū)高度,同時(shí)容器的父級(jí)元素 overflow 屬性值設(shè)為 hidden ,通過(guò)更改容器 top 值實(shí)現(xiàn)全屏滾動(dòng)效果。

如何使用ES6寫(xiě)全屏滾動(dòng)插件

2.2 代碼架構(gòu)

代碼編寫(xiě)的思路是通過(guò) class 定義全屏滾動(dòng)類(lèi),使用時(shí)通過(guò) new PureFullPage().init() 使用。

/**
 * 全屏滾動(dòng)類(lèi)
 */
class PureFullPage {
 // 構(gòu)造函數(shù)
 constructor() {}

 // 原型方法
 methods() {}

 // 初始化函數(shù)
 init() {}
}

3)html 結(jié)構(gòu)

鑒于上述實(shí)現(xiàn)原理,對(duì)于 html 的結(jié)構(gòu)有特定要求,如下:頁(yè)面容器為 #pureFullPageContainer ,所有的頁(yè)面為其直接子元素,這里為了方便,直接取 body 為其直接父元素。

<body>
 <div id="pureFullPageContainer">
  <div class="page"></div>
  <div class="page"></div>
  <div class="page"></div>
 </div>
</body>

4)css 設(shè)置

首先,容器及容器內(nèi)的頁(yè)面取當(dāng)前可視區(qū)高度,為每次切換都顯示一個(gè)完整的頁(yè)面做準(zhǔn)備;

第二,容器的父級(jí)元素(此處是 body ) overflow 屬性值定為 hidden ,這樣可以保證每次只會(huì)顯示一個(gè)頁(yè)面,其他頁(yè)面被隱藏。

經(jīng)過(guò)上述設(shè)置,對(duì)容器 top 值,每次更改一個(gè)可視區(qū)高度的距離,便實(shí)現(xiàn)了頁(yè)面間的切換,部分代碼如下:

body {
 /* body 為容器直接的父元素 */
 overflow: hidden;
}

#pureFullPage {
 /* 只有當(dāng) position 的值不是 static 時(shí),top 值才有效 */
 position: relative;
 /* 設(shè)置初始值 */
 top: 0;
}
.page {
 /* 此處不能為 100vh,后面詳述 */
 /* 其父元素,也就是 #pureFullPage 的高度,通過(guò) js 動(dòng)態(tài)設(shè)置*/
 height: 100%;
}

Notice:

容器的 position 屬性值需要設(shè)置為 relative ,因?yàn)?top 只有在 position 屬性值不為 static 時(shí)才有效;

頁(yè)面高度需設(shè)置為當(dāng)前可視區(qū)高度,但不能直接設(shè)置為 100vh ,因?yàn)?safari 手機(jī)瀏覽器把地址欄算進(jìn)去計(jì)算 100vh ,但地址欄下面的不應(yīng)該算做“可視區(qū)”,畢竟實(shí)際上是“看不見(jiàn)”的區(qū)域。這會(huì)導(dǎo)致 100vh 對(duì)應(yīng)的像素值比 document.documentElement.clientHeight 獲取的像素值大。這樣在切換 top 值時(shí)就不是全屏切換了,實(shí)際上,這種情況下切換的高度小于頁(yè)面的高度。

解決 safari 手機(jī)瀏覽器可視區(qū)高度問(wèn)題:既然通過(guò) js 獲取的 document.documentElement.clientHeight 值是符合預(yù)期的可視區(qū)高度(不包括頂部地址欄和底部工具欄),那就 將該值通過(guò) js 設(shè)置為容器的高度,同時(shí),容器內(nèi)的頁(yè)面高度設(shè)置為 100% ,這樣就可以保證容器及頁(yè)面的高度和切換 top 值相同了,也就保證了全屏切換。

// 偽代碼
'#pureFullPage'.style.height = document.documentElement.clientHeight + 'px';

5)監(jiān)控滾動(dòng)/滑動(dòng)事件

這里的滾動(dòng)/滑動(dòng)事件包括鼠標(biāo)滾動(dòng)、觸摸板滑動(dòng)以及手機(jī)屏幕上下滑動(dòng)。

5.1 PC 端

PC 端主要解決的問(wèn)題是獲取鼠標(biāo)滾動(dòng)或觸摸板滑動(dòng)方向,觸摸板上下滑動(dòng)和鼠標(biāo)滾動(dòng)綁定的是同一個(gè)事件:

  1. firefox 是 DOMMouseScroll 事件,對(duì)應(yīng)的滾輪信息(向前滾還是向后滾)存儲(chǔ)在 detail 屬性中,向前滾,這個(gè)屬性值是 3 的倍數(shù),反之,是 -3 的倍數(shù);

  2. firefox 之外的其他瀏覽器是 mousewheel 事件,對(duì)應(yīng)的滾輪信息存儲(chǔ)在 wheelDelta 屬性中,向前滾,這個(gè)屬性值是 -120 的倍數(shù),反之, 120 的倍數(shù)。

macOS 如此,windows 相反?

所以,可以通過(guò) detail 或 wheelDelta 的值判斷鼠標(biāo)的滾動(dòng)方向,進(jìn)而控制頁(yè)面是向上還是向下滾動(dòng)。在這里我們只關(guān)心正負(fù),不關(guān)心具體值的大小,為了便于使用,下面基于這兩個(gè)事件封裝了一個(gè)函數(shù):如果鼠標(biāo)往前滾動(dòng),返回負(fù)數(shù),反之,返回正數(shù),代碼如下:

// 鼠標(biāo)滾輪事件
getWheelDelta(event) {
 if (event.wheelDelta) {
  return event.wheelDelta;
 } else {
  // 兼容火狐
  return -event.detail;
 }
},

有了滾動(dòng)事件,就可以據(jù)此編寫(xiě)頁(yè)面向上或者向下滾動(dòng)的回調(diào)函數(shù)了,如下:

// 鼠標(biāo)滾動(dòng)邏輯(全屏滾動(dòng)關(guān)鍵邏輯)
scrollMouse(event) {
 let delta = utils.getWheelDelta(event);
 // delta < 0,鼠標(biāo)往前滾動(dòng),頁(yè)面向下滾動(dòng)
 if (delta < 0) {
  this.goDown();
 } else {
  this.goUp();
 }
}

goDown 、 goUp 是頁(yè)面滾動(dòng)的邏輯代碼,需要特別說(shuō)明的是必須 判斷滾動(dòng)邊界,保證容器中顯示的始終是頁(yè)面內(nèi)容 :

  1. 上邊界容易確定,為 1 個(gè)頁(yè)面(也即可視區(qū))的高度,即如果容器當(dāng)前的上外邊框距離整個(gè)頁(yè)面頂部的距離(這里此值正是容器的 offsetTop 值的絕對(duì)值,因?yàn)樗冈氐?offsetTop 值都是 0 )大于等于當(dāng)前可視區(qū)高度時(shí),才允許向上滾動(dòng),不然,就證明上面已經(jīng)沒(méi)有頁(yè)面了,不允許繼續(xù)向上滾動(dòng);

  2. 下邊界為 n - 2 (n 表示全屏滾動(dòng)的頁(yè)面數(shù)) 個(gè)可視區(qū)的高度,當(dāng)容器的 offsetTop 值的絕對(duì)值小于等于 n - 2 個(gè)可視區(qū)的高度時(shí),表示還可以向下滾動(dòng)一個(gè)頁(yè)面。

具體代碼如下:

goUp() {
 // 只有頁(yè)面頂部還有頁(yè)面時(shí)頁(yè)面向上滾動(dòng)
 if (-this.container.offsetTop >= this.viewHeight) {
  // 重新指定當(dāng)前頁(yè)面距視圖頂部的距離 currentPosition,實(shí)現(xiàn)全屏滾動(dòng),
  // currentPosition 為負(fù)值,越大表示超出頂部部分越少
  this.currentPosition = this.currentPosition + this.viewHeight;

  this.turnPage(this.currentPosition);
 }
}
goDown() {
 // 只有頁(yè)面底部還有頁(yè)面時(shí)頁(yè)面向下滾動(dòng)
 if (-this.container.offsetTop <= this.viewHeight * (this.pagesNum - 2)) {
  // 重新指定當(dāng)前頁(yè)面距視圖頂部的距離 currentPosition,實(shí)現(xiàn)全屏滾動(dòng),
  // currentPosition 為負(fù)值,越小表示超出頂部部分越多
  this.currentPosition = this.currentPosition - this.viewHeight;

  this.turnPage(this.currentPosition);
 }
}

最后添加滾動(dòng)事件:

// 鼠標(biāo)滾輪監(jiān)聽(tīng),火狐鼠標(biāo)滾動(dòng)事件不同其他
if (navigator.userAgent.toLowerCase().indexOf('firefox') === -1) {
 document.addEventListener('mousewheel', scrollMouse);
} else {
 document.addEventListener('DOMMouseScroll', scrollMouse);
}

5.2 移動(dòng)端

移動(dòng)端需要判斷是向上還是向下滑動(dòng),可以結(jié)合 touchstart (手指開(kāi)始接觸屏幕時(shí)觸發(fā)) 和 touchend (手指離開(kāi)屏幕時(shí)觸發(fā)) 兩個(gè)事件實(shí)現(xiàn)判斷:分別獲取兩個(gè)事件開(kāi)始觸發(fā)時(shí)的 pageY 值,如果觸摸結(jié)束時(shí)的 pageY 大于觸摸開(kāi)始時(shí)的 pageY ,表示手指向下滑動(dòng),對(duì)應(yīng)頁(yè)面向上滾動(dòng),反之亦然。

此處我們需要觸摸事件跟蹤觸摸的屬性:

  1. touches :當(dāng)前跟蹤的觸摸操作的 Touch 對(duì)象的數(shù)組,用于獲取觸摸開(kāi)始時(shí)的 pageY 值;

  2. changeTouches :自上次觸摸以來(lái)發(fā)生了改變的 Touch 對(duì)象的數(shù)組,用于獲取觸摸觸摸結(jié)束時(shí)的 pageY 值。

相關(guān)代碼如下:

// 手指接觸屏幕
document.addEventListener('touchstart', event => {
 this.startY = event.touches[0].pageY;
});
//手指離開(kāi)屏幕
document.addEventListener('touchend', event => {
 let endY = event.changedTouches[0].pageY;
 if (endY - this.startY < 0) {
  // 手指向上滑動(dòng),對(duì)應(yīng)頁(yè)面向下滾動(dòng)
  this.goDown();
 } else {
  // 手指向下滑動(dòng),對(duì)應(yīng)頁(yè)面向上滾動(dòng)
  this.goUp();
 }
});

為了避免下拉刷新,可以阻止 touchmove 事件的默認(rèn)行為:

// 阻止 touchmove 下拉刷新
document.addEventListener('touchmove', event => {
 event.preventDefault();
});

6)PC 端滾動(dòng)事件性能優(yōu)化

6.1 防抖函數(shù)和截流函數(shù)介紹

優(yōu)化主要從兩方便入手:

  1. 更改頁(yè)面大小時(shí),通過(guò)防抖動(dòng)(debounce)函數(shù)限制 resize 事件觸發(fā)頻率;

  2. 滾動(dòng)/滑動(dòng)事件觸發(fā)時(shí),通過(guò)截流(throttle)函數(shù)限制滾動(dòng)/滑動(dòng)事件觸發(fā)頻率。

既然都是限制觸發(fā)頻率(都通過(guò)定時(shí)器實(shí)現(xiàn)),那這兩者有什么區(qū)別?

首先,防抖動(dòng)函數(shù)工作時(shí),如果在指定的延遲時(shí)間內(nèi),某個(gè)事件連續(xù)觸發(fā),那么綁定在這個(gè)事件上的回調(diào)函數(shù)永遠(yuǎn)不會(huì)觸發(fā),只有在延遲時(shí)間內(nèi),這個(gè)事件沒(méi)再觸發(fā),對(duì)應(yīng)的回調(diào)函數(shù)才會(huì)執(zhí)行。防抖動(dòng)函數(shù)非常適合改變窗口大小這一事件,這也符合 拖動(dòng)到位以后再觸發(fā)事件,如果一直拖個(gè)不停,始終不觸發(fā)事件 這一直覺(jué)。

而截流函數(shù)是在延遲時(shí)間內(nèi),綁定到事件上的回調(diào)函數(shù)能且只能觸發(fā)一次,這和截流函數(shù)不同,即便是在延遲時(shí)間內(nèi)連續(xù)觸發(fā)事件,也不會(huì)阻止在延遲時(shí)間內(nèi)有一個(gè)回調(diào)函數(shù)執(zhí)行。并且截流函數(shù)允許我們指定回調(diào)函數(shù)是在延遲時(shí)間開(kāi)始時(shí)還是結(jié)束時(shí)執(zhí)行。

鑒于截流函數(shù)的上述兩個(gè)特性,尤其適合優(yōu)化滾動(dòng)/滑動(dòng)事件:

  1. 可以限制頻率;

  2. 不會(huì)因?yàn)闈L動(dòng)/滑動(dòng)事件太靈敏(在延遲時(shí)間內(nèi)不斷觸發(fā))導(dǎo)致注冊(cè)在事件上的回調(diào)函數(shù)無(wú)法執(zhí)行;

  3. 可以設(shè)置在延遲時(shí)間開(kāi)始時(shí)觸發(fā)回調(diào)函數(shù),從而避免用戶(hù)感到操作之后的短暫延時(shí)。

這里不介紹防抖動(dòng)函數(shù)和截流函數(shù)的實(shí)現(xiàn)原理,感興趣的可以看 Throttling and Debouncing in JavaScript ,下面是實(shí)現(xiàn)的代碼:

// 防抖動(dòng)函數(shù),method 回調(diào)函數(shù),context 上下文,event 傳入的時(shí)間,delay 延遲函數(shù)
debounce(method, context, event, delay) {
 clearTimeout(method.tId);
 method.tId = setTimeout(() => {
  method.call(context, event);
 }, delay);
},

// 截流函數(shù),method 回調(diào)函數(shù),context 上下文,delay 延遲函數(shù),
// immediate 傳入 true 表示在 delay 開(kāi)始時(shí)執(zhí)行回調(diào)函數(shù)
throttle(method, context, delay, immediate) {
 return function() {
  const args = arguments;
  const later = () => {
   method.tID = null;
   if (!immediate) {
    method.apply(context, args);
   }
  };
  const callNow = immediate && !method.tID;
  clearTimeout(method.tID);
  method.tID = setTimeout(later, delay);
  if (callNow) {
   method.apply(context, args);
  }
 };
},

《JavaScript 高級(jí)程序設(shè)計(jì) - 第三版》 22.33.3 節(jié)中介紹的 throttle 函數(shù)和此處定義的不同,高程中定義的 throttle 函數(shù)對(duì)應(yīng)此處的 debounce 函數(shù),但網(wǎng)上大多數(shù)文章都和高程中的不同,比如 lodash 中定義的 debounce 。

6.2 改造 PC 端滾動(dòng)事件

通過(guò)上述說(shuō)明,我們已經(jīng)知道截流函數(shù)可以通過(guò)限定滾動(dòng)事件觸發(fā)頻率提升性能,同時(shí),設(shè)置在 延遲時(shí)間開(kāi)始階段立即調(diào)用滾動(dòng)事件的回調(diào)函數(shù) 并不會(huì)犧牲用戶(hù)體驗(yàn)。

截流函數(shù)上文已經(jīng)定義好,使用起來(lái)就很簡(jiǎn)單了:

// 設(shè)置截流函數(shù)
let handleMouseWheel = utils.throttle(this.scrollMouse, this, this.DELAY, true);

// 鼠標(biāo)滾輪監(jiān)聽(tīng),火狐鼠標(biāo)滾動(dòng)事件不同其他
if (navigator.userAgent.toLowerCase().indexOf('firefox') === -1) {
 document.addEventListener('mousewheel', handleMouseWheel);
} else {
 document.addEventListener('DOMMouseScroll', handleMouseWheel);
}

上面這部分代碼是寫(xiě)在 class 的 init 方法中,所以截流函數(shù)的上下文(context)傳入的是 this ,表示當(dāng)前 class 實(shí)例。

7)其他

7.1 導(dǎo)航按鈕

為了簡(jiǎn)化 html 結(jié)構(gòu),導(dǎo)航按鈕通過(guò) js 創(chuàng)建。這里的難點(diǎn)在于 如何實(shí)現(xiàn)點(diǎn)擊不同按鈕實(shí)現(xiàn)對(duì)應(yīng)頁(yè)面的跳轉(zhuǎn)并更新對(duì)應(yīng)按鈕的樣式 。

解決的思路是:

  1. 頁(yè)面跳轉(zhuǎn):頁(yè)面?zhèn)€數(shù)和導(dǎo)航按鈕的個(gè)數(shù)一致,所以點(diǎn)擊第 i 個(gè)按鈕也就是跳轉(zhuǎn)到第 i 個(gè)頁(yè)面,而第 i 個(gè)頁(yè)面對(duì)應(yīng)的容器 top 值恰好是 -(i * this.viewHeight)

  2. 更改樣式:更改樣式即先刪除所有按鈕的選中樣式,然后給當(dāng)前點(diǎn)擊的按鈕添加選中樣式。

// 創(chuàng)建右側(cè)點(diǎn)式導(dǎo)航
createNav() {
 const nav = document.createElement('div');
 nav.className = 'nav';
 this.container.appendChild(nav);
 // 有幾頁(yè),顯示幾個(gè)點(diǎn)
 for (let i = 0; i < this.pagesNum; i++) {
  nav.innerHTML += '<p class="nav-dot"><span></span></p>';
 }
 const navDots = document.querySelectorAll('.nav-dot');
 this.navDots = Array.prototype.slice.call(navDots);
 // 添加初始樣式
 this.navDots[0].classList.add('active');
 // 添加點(diǎn)式導(dǎo)航點(diǎn)擊事件
 this.navDots.forEach((el, i) => {
  el.addEventListener('click', event => {
   // 頁(yè)面跳轉(zhuǎn)
   this.currentPosition = -(i * this.viewHeight);
   this.turnPage(this.currentPosition);
   // 更改樣式
   this.navDots.forEach(el => {
    utils.deleteClassName(el, 'active');
   });
   event.target.classList.add('active');
  });
 });
}

7.2 自定義參數(shù)

得當(dāng)?shù)淖远x參數(shù)可以增加插件的靈活性。

參數(shù)通過(guò)構(gòu)造函數(shù)傳入,并通過(guò) Object.assign() 進(jìn)行參數(shù)合并:

constructor(options) {
 // 默認(rèn)配置
 const defaultOptions = {
  isShowNav: true,
  delay: 150,
  definePages: () => {},
 };
 // 合并自定義配置
 this.options = Object.assign(defaultOptions, options);
}

7.3 窗口尺寸改變時(shí)更新數(shù)據(jù)

瀏覽器窗口尺寸改變的時(shí)候,需要重新獲取可視區(qū)、頁(yè)面元素高度,并重新確定容器當(dāng)前的 top 值。

同時(shí),為了避免不必要的性能開(kāi)支,這里使用了防抖動(dòng)函數(shù)。

// window resize 時(shí)重新獲取位置
getNewPosition() {
 this.viewHeight = document.documentElement.clientHeight;
 this.container.style.height = this.viewHeight + 'px';
 let activeNavIndex;
 this.navDots.forEach((e, i) => {
  if (e.classList.contains('active')) {
   activeNavIndex = i;
  }
 });
 this.currentPosition = -(activeNavIndex * this.viewHeight);
 this.turnPage(this.currentPosition);
}

handleWindowResize(event) {
 // 設(shè)置防抖動(dòng)函數(shù)
 utils.debounce(this.getNewPosition, this, event, this.DELAY);
}

// 窗口尺寸變化時(shí)重置位置
window.addEventListener('resize', this.handleWindowResize.bind(this));

7.4 兼容性

這里的兼容性主要指兩個(gè)方面:一是不同瀏覽器對(duì)同一行為定義了不同 API,比如上文提到的獲取鼠標(biāo)滾動(dòng)信息的 API Firefox 和其他瀏覽器不一樣;第二點(diǎn)就是 ES6 新語(yǔ)法、新 API 的兼容處理。

對(duì)于 class、箭頭函數(shù)這類(lèi)新語(yǔ)法的轉(zhuǎn)換,通過(guò) babel 就可完成,鑒于本插件代碼量很小,都處于可控的狀態(tài),并沒(méi)有引入 babel 提供的 polyfill 方案,因?yàn)樾?API 只有 Object.assign() 需要做兼容處理,單獨(dú)寫(xiě)個(gè) polyfill 就好,如下:

// polyfill Object.assign
polyfill() {
 if (typeof Object.assign != 'function') {
  Object.defineProperty(Object, 'assign', {
   value: function assign(target, varArgs) {
    if (target == null) {
     throw new TypeError('Cannot convert undefined or null to object');
    }
    let to = Object(target);
    for (let index = 1; index < arguments.length; index++) {
     let nextSource = arguments[index];
     if (nextSource != null) {
      for (let nextKey in nextSource) {
       if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
        to[nextKey] = nextSource[nextKey];
       }
      }
     }
    }
    return to;
   },
   writable: true,
   configurable: true,
  });
 }
},

引用自: MDN-Object.assign()

因?yàn)楸静寮患嫒莸?IE10,所以不打算對(duì)事件做兼容處理,畢竟IE9 都支持 addEventListener 了。

7.5 通過(guò)惰性載入進(jìn)一步優(yōu)化性能

在 5.1 中寫(xiě)的 getWheelDelta 函數(shù)每次執(zhí)行都需要檢測(cè)是否支持 event.wheelDelta ,實(shí)際上,瀏覽器只需在第一次加載時(shí)檢測(cè),如果支持,接下來(lái)都會(huì)支持,再做檢測(cè)是沒(méi)必要的。

并且這個(gè)檢測(cè)在頁(yè)面的生命周期中會(huì)執(zhí)行很多次,這種情況下可以通過(guò) 惰性載入 技巧進(jìn)行優(yōu)化,如下:

getWheelDelta(event) {
 if (event.wheelDelta) {
  // 第一次調(diào)用之后惰性載入,無(wú)需再做檢測(cè)
  this.getWheelDelta = event => event.wheelDelta;
  // 第一次調(diào)用使用
  return event.wheelDelta;
 } else {
  // 兼容火狐
  this.getWheelDelta = event => -event.detail;
  return -event.detail;
 }
},

以上是“如何使用ES6寫(xiě)全屏滾動(dòng)插件”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

es6
AI