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

JS的window.addEventListener仅单页生效及offset未定义报错问题

解决元素可见性检测函数仅单页生效且报错的问题

问题根源分析

你碰到的TypeError: $elem.offset(...) is undefined报错,本质原因是其他页面不存在你代码中检测的部分元素(比如#lfdesign、#books这类选择器对应的DOM节点)。当jQuery尝试获取不存在元素的offset()属性时,会直接返回undefined,导致代码执行中断,整个滚动事件的处理逻辑也就失效了。

修复方案

1. 先完善isOnScreen函数的空元素判断

原函数里的空元素判断只是直接return,但没有返回明确的布尔值,后续代码还是会尝试执行offset()操作。我们修改成直接返回false,并提前获取jQuery对象做判断:

function isOnScreen(elem) {
    var $elem = jQuery(elem);
    // 元素不存在直接返回false,避免后续报错
    if ($elem.length === 0) {
        return false;
    }
    var $window = jQuery(window)
    var viewport_top = $window.scrollTop()
    var viewport_height = $window.height()
    var viewport_bottom = viewport_top + viewport_height
    var top = $elem.offset().top
    var height = $elem.height()
    var bottom = top + height
    return (bottom > viewport_top) && (top < viewport_bottom)
}

2. 优化滚动事件逻辑(可选但推荐)

滚动事件触发频率极高,建议加上防抖函数减少性能消耗,同时给已添加动画的元素做标记,避免重复操作:

// 防抖函数:控制事件触发频率
function debounce(func, wait) {
    let timeout;
    return function() {
        const context = this;
        const args = arguments;
        clearTimeout(timeout);
        timeout = setTimeout(() => func.apply(context, args), wait);
    };
}

// 用防抖包装滚动事件处理函数
window.addEventListener('scroll', debounce(function (e) {
    // 统一管理所有需要动画的元素配置
    const animateConfigs = [
        { target: '#lfdesign', animateClass: 'animated slower bounceInRight' },
        { target: '#books', animateClass: 'animated slower bounceInLeft' },
        { target: '.srp-color', animateClass: 'animated slower bounceInRight' },
        { target: '.nescol-color', animateClass: 'animated slower bounceInLeft' },
        { target: '.worldskills-color', animateClass: 'animated slower bounceInRight' },
        { target: '.silvernote-color', animateClass: 'animated slower bounceInLeft' }
    ];

    animateConfigs.forEach(config => {
        const $container = jQuery(`${config.target} .flexcontainer`);
        // 容器不存在或已添加动画类,直接跳过
        if ($container.length === 0 || $container.hasClass('animated')) return;
        // 元素进入视口时添加动画类
        if (isOnScreen(config.target)) {
            $container.addClass(config.animateClass);
        }
    });
}, 100)); // 100ms防抖延迟,可根据需求调整

3. 进阶方案:使用Intersection Observer API替代滚动监听

现代浏览器支持的Intersection Observer API比滚动监听更高效,它能自动检测元素是否进入视口,无需手动计算位置,也不用处理防抖:

// 初始化观察器
const observer = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
        if (entry.isIntersecting) {
            const $container = jQuery(entry.target).find('.flexcontainer');
            // 根据目标元素的标识添加对应动画类
            const target = entry.target;
            if (target.id === 'lfdesign' || target.classList.contains('srp-color') || target.classList.contains('worldskills-color')) {
                $container.addClass('animated slower bounceInRight');
            } else if (target.id === 'books' || target.classList.contains('nescol-color') || target.classList.contains('silvernote-color')) {
                $container.addClass('animated slower bounceInLeft');
            }
            // 元素进入视口后停止观察,避免重复触发
            observer.unobserve(entry.target);
        }
    });
}, { threshold: 0.1 }); // 元素10%进入视口时触发动画

// 批量观察目标元素,不存在的元素会自动跳过
['#lfdesign', '#books', '.srp-color', '.nescol-color', '.worldskills-color', '.silvernote-color'].forEach(selector => {
    const elem = document.querySelector(selector);
    if (elem) observer.observe(elem);
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 14:02:54