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

纯JavaScript实现滚动添加is-page-scrolled类异常排查

问题描述

我正尝试将一段jQuery代码迁移为纯JavaScript代码。原jQuery代码会在用户滚动到body元素data属性data-page-scrolled-offset指定的偏移量时,为body元素切换is-page-scrolled类;当用户滚动回页面顶部时,该类会被移除。

原可用jQuery代码

var scrolled_page_offset = parseInt( $( 'body' ).data( 'pageScrolledOffset' ) );
var scrolled_page = function() {
    var scroll_top = window.pageYOffset;
    $( 'body' ).toggleClass( 'is-page-scrolled', scroll_top > scrolled_page_offset );
};

$( window ).on( 'scroll', function() {
    scrolled_page();
} );

scrolled_page();

无法正常工作的纯JavaScript代码

var scrolled_page_offset = parseInt( document.body.dataset.pageScrolledOffset );
var scrolled_page = function() {
    var scroll_top = window.pageYOffset;
    if ( scroll_top > scrolled_page_offset ) {
        document.body.classList.toggle( 'is-page-scrolled' );
    }
};

window.addEventListener( 'scroll', function() {
    scrolled_page();
} );

scrolled_page();

我编写的纯JavaScript代码无法正常工作,用户向下滚动页面时,is-page-scrolled类会被间歇性反复切换。请问我哪里出错了?

问题原因与修复方案

核心错误

你混淆了jQuery的toggleClass和原生JS的classList.toggle的行为差异:

  • jQuery的toggleClass(className, state)第二个参数是布尔值,用来强制决定类的添加/移除:true就添加,false就移除,不会反复切换状态。
  • 你写的原生代码里,只在scroll_top > scrolled_page_offset时调用classList.toggle('is-page-scrolled'),这意味着每次滚动触发这个条件时,类都会被切换一次(有则删,无则加),所以会出现间歇性反复切换的问题。同时,你完全没处理滚动回偏移量以内的情况,类根本不会被移除。

修复方案

有两种写法可以实现和原jQuery一致的效果:

方案1:使用classList.add和classList.remove(兼容性最好)

var scrolled_page_offset = parseInt(document.body.dataset.pageScrolledOffset);
var scrolled_page = function() {
    var scroll_top = window.pageYOffset;
    if (scroll_top > scrolled_page_offset) {
        document.body.classList.add('is-page-scrolled');
    } else {
        document.body.classList.remove('is-page-scrolled');
    }
};

window.addEventListener('scroll', scrolled_page);
scrolled_page();

方案2:使用原生toggle的第二个参数(现代浏览器支持)

原生classList.toggle其实也支持第二个布尔参数,和jQuery的逻辑完全一致:

var scrolled_page_offset = parseInt(document.body.dataset.pageScrolledOffset);
var scrolled_page = function() {
    var scroll_top = window.pageYOffset;
    // 第二个参数为true时添加类,false时移除类
    document.body.classList.toggle('is-page-scrolled', scroll_top > scrolled_page_offset);
};

window.addEventListener('scroll', scrolled_page);
scrolled_page();

额外优化

滚动事件触发频率很高,建议加上防抖优化,避免频繁操作DOM:

var scrolled_page_offset = parseInt(document.body.dataset.pageScrolledOffset);
var scrolled_page = function() {
    var scroll_top = window.pageYOffset;
    document.body.classList.toggle('is-page-scrolled', scroll_top > scrolled_page_offset);
};

// 防抖函数
function debounce(func, delay = 100) {
    let timer;
    return function() {
        clearTimeout(timer);
        timer = setTimeout(func, delay);
    };
}

window.addEventListener('scroll', debounce(scrolled_page));
scrolled_page();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 03:10:48