項(xiàng)目中關(guān)于監(jiān)聽和移除scroll的坑

項(xiàng)目背景:當(dāng)進(jìn)入頁面滾動的時(shí)候,頁面中的元素出現(xiàn)在視野的時(shí)候,展示一下動畫效果。
技術(shù)棧:vue
實(shí)現(xiàn)方法:主要是給需要動畫的元素添加animation+X/Y/L/R class樣式

解決什么問題:

  1. 網(wǎng)上的好多滾動事件沒有添加防抖函數(shù),這樣會導(dǎo)致在滾動過程中會有白屏現(xiàn)象。
  2. 另外就是沒有移除事件監(jiān)聽,在離開當(dāng)前頁面的時(shí)候,需要在銷毀組件之前移除滾動事件,否則跳轉(zhuǎn)路由之后,事件仍然會被調(diào)用,浪費(fèi)資源
  3. 為什么不直接 window.addEventListener('scroll', throttle(this.handleScroll, 0, 500))這樣寫?因?yàn)槲野l(fā)現(xiàn)這樣在remove的時(shí)候移除不了。所以監(jiān)聽處理寫個(gè)聲明式函數(shù)、或者用函數(shù)表達(dá)式賦值給變量比較好些,這樣移除事件監(jiān)聽方便些。

開始吧

/**
 * 在 mounted() 的時(shí)候(el 被新創(chuàng)建的 vm.$el 替換,并掛載到實(shí)例上去之后調(diào)用該鉤子。)
 * 添加事件監(jiān)聽 
 */
    this.throttleLoad = throttle(this.handleScroll, 0, 500)
    window.addEventListener('scroll', this.throttleLoad)
    this.handleScroll() // 并首次調(diào)用動畫(可能有些元素在不同尺寸的屏幕下,有可能需要執(zhí)行動畫)

methods 中監(jiān)聽調(diào)用的方法

  // 不同頁面調(diào)用不同的方法
    handleScroll(e) {
      const clientH = window.innerHeight
      const boxListL = [...document.querySelectorAll('.animationL')]
      boxListL.forEach((item, index) => {
        const Rect = item.getBoundingClientRect()
        if (Rect.top + 130 < clientH) {
          handleAddClass(item, 'animation-activeL')
        } else {
          handleRemoveClass(item, 'animation-activeL')
        }
      })
      const boxListR = [...document.querySelectorAll('.animationR')]
      boxListR.forEach((item, index) => {
        const Rect = item.getBoundingClientRect()
        if (Rect.top + 130 < clientH) {
          handleAddClass(item, 'animation-activeR')
        } else {
          handleRemoveClass(item, 'animation-activeR')
        }
      })
    }
  }

主動銷毀

  beforeDestroy() {
    window.removeEventListener('scroll', this.throttleLoad)
  }

公共的方法抽離出來放到公共js中

// 因?yàn)楫?dāng)時(shí)考慮到兼容問題,在IE低版本中沒有classList.add / remove 這些方法
/**
 * Add class
 * @param {DOM} item
 * @param {className} name
 */
export function handleAddClass(item, name) {
  if (item.classList) {
    item.classList.add(name)
  } else {
    const classes = item.className.split(/\s+/g)
    if (classes.indexOf(name) < 0) {
      classes.push(name)
    }
    item.className = classes.join(' ')
  }
}
/**
 * Remove class
 * @param {DOM} item
 * @param {className} name
 */
export function handleRemoveClass(item, name) {
  if (item.classList) {
    item.classList.remove(name)
  } else {
    const classes = item.className.split(/\s+/g)
    const n = classes.indexOf('animation-activeL')
    if (n > -1) {
      classes.splice(n, 1)
    }
    item.className = classes.join(' ')
  }
}
/**
 * 防抖
 * @param fn 執(zhí)行的函數(shù)
 * @param delay 延時(shí)時(shí)間
 * @param atleast 達(dá)到強(qiáng)制執(zhí)行的條件
 */
export function throttle(fn, delay, atleast) {
  let timer = null
  let previous = null
  return function () {
    const now = +new Date()
    if (!previous) previous = now
    if (atleast && now - previous > atleast) {
      fn()
      previous = now
      clearTimeout(timer)
    } else {
      clearTimeout(timer)
      timer = setTimeout(function () {
        fn()
        previous = null
      }, delay)
    }
  }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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