使用惰性函数优化页面滚动事件的性能

我们在做前端开发的时候,曾遇到一些非常炫酷的宣传页。例如每一个苹果产品的主页面。我们会发现,这样炫酷的页面,总是跟随我们鼠标滚轮的操作,在页面中响应不同的事件。


一、浏览器的不同

我们都知道,需要在前端页面中监听到鼠标滚轮的事件,不同浏览器内核提供的方法是不同的。所以,每当我们需要监听鼠标滚轮事件,就需要先判断使用终端是用的什么浏览器。

在前端,我们可以通过 window.navigator.userAgent 这个浏览器自带的 API 来判断浏览器类型。其中,Chrome、FireFox、Edge 这三个如今最主流的浏览器,返回的格式如下:

浏览器userAgent 返回值
ChromeMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36
FireFoxMozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0
EdgeMozilla/5.0 (Windows NT 10.0; Win64; x64; ServiceUI 13) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134

 

 

 

 

 

由于鼠标滚轮事件,只有 FireFox 浏览器比较特殊,其它浏览器都是一样的。所以我们只需要判断是否是 FireFox 浏览器即可。

const browser = window.navigator.userAgent; // 获取浏览器信息
const isFirefox = browser.toLowerCase().includes('firefox'); // 判断是不是 FireFox 浏览器

二、监听滚动事件

在 Chrome 等主流浏览器中,我们可以直接通过监听 mousewheel 事件。其对应事件处理函数中的事件对象 event 包含一个 wheelDelta 属性。当鼠标滚轮向上滚动的时候,wheelDelta 的值为 120;反之,当鼠标滚轮向下滚动的时候,wheelDelta 的值为 -120

因此,我们可以直接通过判断 wheelDelta 的值,获取对应的操作逻辑:

document.addEventListener('mousewheel', function(e) { // 其它浏览器使用 mousewheel 监听
  const ev = e || event;
  ev.wheelDelta > 0 ? console.log('向上滚动') : console.log('向下滚动'); // wheelDelta 为 -120,向下滚动;wheelDelta 为 120,向上滚动
});

在 FireFox 浏览器中,我们需要通过监听 DOMMouseScroll 事件。其对应事件处理函数中的事件对象 event 并不包含 wheelDelta 属性,而是使用 detail 代替。并且,detail 属性的值也是和事件反过来的。当鼠标滚轮向上滚动的时候,detail 的值为 -3;反之,当鼠标滚轮向下滚动的时候,detail 的值为 3

因此,在 FireFox 浏览器中,我们需要通过判断 detail 的值来获取对应的操作逻辑:

document.addEventListener('DOMMouseScroll', function(e) { // FireFox 浏览器使用 DOMMouseScroll 监听
  const ev = e || event;
  ev.detail < 0 ? console.log('向上滚动') : console.log('向下滚动'); // detail 为 3,向下滚动;detail 为 -3,向上滚动
});

 


三、完整的监听滚动函数

通过以上两步,我们可以简单的将其构建成一个完整的监听鼠标滚动的通用函数:

function scroll() {
  const browser = window.navigator.userAgent; // 获取浏览器信息
  const isFirefox = browser.toLowerCase().includes('firefox'); // 判断是不是 FireFox 浏览器
  if (isFirefox) {
    document.addEventListener('DOMMouseScroll', function(e) { // FireFox 浏览器使用 DOMMouseScroll 监听
      const ev = e || event;
      ev.detail < 0 ? console.log('向上滚动') : console.log('向下滚动'); // detail 为 3,向下滚动;detail 为 -3,向上滚动
    });
  } else {
    document.addEventListener('mousewheel', function(e) { // 其它浏览器使用 mousewheel 监听
      const ev = e || event;
      ev.wheelDelta > 0 ? console.log('向上滚动') : console.log('向下滚动'); // wheelDelta 为 -120,向下滚动;wheelDelta 为 120,向上滚动
    });
  }
}

 一般来说,函数写成,大功告成。但是咱们不妨思考这样一个问题:

对于同一个浏览器来说,每次进来都要判断浏览器类型,并做出判断,这样做是必须的吗?

比如一个 Chrome 浏览器,在第一次访问的时候,程序需要判断浏览器类型,并根据判断执行以上程序中 else 的部分。那么,从第二次开始同一个 Chrome 浏览器进行访问的时候,可以直接执行 else 部分中的代码即可,何乐而不为呢?

这样,掌声有请我们今天的主角——惰性函数。


四、惰性函数 

通过打印,我们可以看到。以上函数在每一次执行的时候,均会完整执行:

 

于是,我们巧妙的借助 JavaScript 中函数声明的特点,对函数名变量进行重新赋值,就可以巧妙地减少执行函数的大小: 

function scroll() {
  const browser = window.navigator.userAgent; // 获取浏览器信息
  const isFirefox = browser.toLowerCase().includes('firefox'); // 判断是不是 FireFox 浏览器
  if (isFirefox) {
    scroll = function () {
      document.addEventListener('DOMMouseScroll', function(e) { // FireFox 浏览器使用 DOMMouseScroll 监听
      const ev = e || event;
      ev.detail < 0 ? console.log('向上滚动') : console.log('向下滚动'); // detail 为 3,向下滚动;detail 为 -3,向上滚动
    });
    }
  } else {
    scroll = function () {
      document.addEventListener('mousewheel', function(e) { // 其它浏览器使用 mousewheel 监听
      const ev = e || event;
      ev.wheelDelta > 0 ? console.log('向上滚动') : console.log('向下滚动'); // wheelDelta 为 -120,向下滚动;wheelDelta 为 120,向上滚动
    });
    }
  }
}

在这里,我们分别把 if 和 else 中的代码都放到一个匿名函数中,并且把匿名函数赋值给一个变量。需要注意的是,这个变量并不是我们自己声明的,而是直接写了父函数的函数名 scroll。 

这里牵扯到 JavaScript 代码在浏览器加载的底层原理,不再过多展开。感兴趣的小伙伴们可以关注我以后的文章,我会在不久的将来做更加详细的讲解。

通过打印,我们发现从第二次开始,执行函数 scroll 不再是整个函数,而仅仅是我们需要执行的匿名函数。 

 

这样处理之后,程序的执行部分得到了大大的简化,也可以提升程序的执行效率。

这样,在函数体中巧用覆盖赋值的方式写的匿名函数方法,我们就叫做惰性函数

 

关注我,给您更多精彩内容!

  • 29
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值