You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决JavaScript中滚动类检测延迟与Android兼容性问题?

滚动方向检测在Android浏览器异常:延迟/失效问题

问题详情

滚动时scrollup和scrolldown类的检测存在延迟,该功能在iOS设备上运行正常,但在Android设备上仅在Mozilla Firefox浏览器中有卡顿地运行,其他浏览器完全无法正常工作。已尝试移除AOS滚动行为、检查SCSS等操作,问题仍未解决。

原代码如下:

/**
 * @file
 * Global utilities.
 *
 */
(function (Drupal) {
  'use strict';
  Drupal.behaviors.bootstrap_barrio = {
    attach: function (context, settings) {
      var position = window.scrollY;
      window.addEventListener('scroll', function() {
        if (window.scrollY > 50) {
          document.querySelector('body').classList.add("scrolled");
        }
        else {
          document.querySelector('body').classList.remove("scrolled");
        }
        var scroll = window.scrollY;
        if (scroll > position) {
          document.querySelector('body').classList.add("scrolldown");
          document.querySelector('body').classList.remove("scrollup");
        } else {
          document.querySelector('body').classList.add("scrollup");
          document.querySelector('body').classList.remove("scrolldown");
        }
        position = scroll;
      });
      document.addEventListener('click', function (event) {
        // If the clicked element doesn't have the right selector, bail
        if (!event.target.matches('.dropdown-item a.dropdown-toggle')) return;
        // Don't follow the link
        event.preventDefault();
        toggle(event.target.next('ul'));
        event.stopPropagation();
      }, false);
      // Toggle element visibility
      var toggle = function (elem) {
        // If the element is visible, hide it
        if (window.getComputedStyle(elem).display === 'block') {
          hide(elem);
          return;
        }
        // Otherwise, show it
        show(elem);
      };
      var show = function (elem) {
        elem.style.display = 'block';
      };
      var hide = function (elem) {
        elem.style.display = 'none';
      };
    }
  };
}
)(Drupal);

问题分析

原代码存在几个核心性能瓶颈:

  1. scroll事件高频触发:Android浏览器对高频事件的主线程分配优先级低,导致回调延迟执行
  2. 重复DOM查询:每次scroll回调都重复调用document.querySelector('body'),增加不必要的性能开销
  3. 无节流控制:未限制回调执行频率,导致主线程被频繁占用,引发卡顿
  4. DOM方法误用:event.target.next('ul')是jQuery语法,原生环境下会失效

解决方案

优化后的代码如下:

(function (Drupal) {
  'use strict';
  Drupal.behaviors.bootstrap_barrio = {
    attach: function (context, settings) {
      // 缓存DOM元素,避免重复查询
      const body = document.querySelector('body');
      if (!body) return;

      let lastScrollY = window.scrollY;
      let ticking = false; // 标记是否已有等待执行的回调

      // 处理滚动逻辑的核心函数
      const updateScrollState = () => {
        const currentScrollY = window.scrollY;

        // 更新scrolled类
        if (currentScrollY > 50) {
          body.classList.add('scrolled');
        } else {
          body.classList.remove('scrolled');
        }

        // 更新滚动方向类,忽略微小滚动波动
        const scrollDelta = currentScrollY - lastScrollY;
        if (Math.abs(scrollDelta) > 2) { // 阈值过滤滚动抖动
          if (scrollDelta > 0) {
            body.classList.add('scrolldown');
            body.classList.remove('scrollup');
          } else {
            body.classList.add('scrollup');
            body.classList.remove('scrolldown');
          }
        }

        lastScrollY = currentScrollY;
        ticking = false;
      };

      // 使用requestAnimationFrame节流scroll事件
      window.addEventListener('scroll', () => {
        if (!ticking) {
          window.requestAnimationFrame(updateScrollState);
          ticking = true;
        }
      }, { passive: true }); // passive优化滚动性能,避免阻塞默认行为

      // 下拉菜单逻辑修复
      document.addEventListener('click', function (event) {
        if (!event.target.matches('.dropdown-item a.dropdown-toggle')) return;
        event.preventDefault();
        toggle(event.target.nextElementSibling); // 替换为原生DOM方法
        event.stopPropagation();
      }, false);

      const toggle = function (elem) {
        if (!elem) return;
        if (window.getComputedStyle(elem).display === 'block') {
          hide(elem);
          return;
        }
        show(elem);
      };

      const show = function (elem) {
        elem.style.display = 'block';
      };

      const hide = function (elem) {
        elem.style.display = 'none';
      };
    }
  };
})(Drupal);

优化说明

  • DOM缓存:提前获取body元素,避免每次scroll回调重复查询DOM
  • 事件节流:通过requestAnimationFrame确保回调只在浏览器重绘前执行一次,降低主线程压力
  • 滚动阈值:忽略小于2px的滚动波动,避免快速滚动时的方向误判
  • passive监听:标记scroll事件为passive,允许浏览器优化滚动性能,避免卡顿
  • 原生DOM方法修复:将jQuery的next()替换为原生nextElementSibling,确保在非jQuery环境下正常运行

内容的提问来源于stack exchange,提问作者osmnfth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 09:35:55