首页 > web前端 > js教程 > 正文

CxJS中实现非被动式滚轮事件监听与默认行为阻止的教程

碧海醫心
发布: 2025-11-01 15:18:00
原创
262人浏览过

CxJS中实现非被动式滚轮事件监听与默认行为阻止的教程

本文详细介绍了在cxjs应用中,如何解决默认onwheel事件的被动监听限制,从而成功阻止其默认行为。通过利用onref属性获取dom元素引用,并结合cx/util中的addeventlistenerwithoptions方法,我们可以灵活地添加非被动式(active)的wheel事件监听器,确保e.preventdefault()功能正常生效,实现对滚轮事件的精确控制。

理解CxJS中的滚轮事件限制

在CxJS应用中,以及其底层框架React中,为了优化滚动性能,诸如onWheel、onTouchStart等触摸和滚轮事件默认被浏览器注册为“被动(passive)”事件监听器。这意味着当这些事件触发时,浏览器不会等待事件处理函数执行完毕,而是会立即处理滚动。这种机制显著提升了页面的滚动流畅度,但也带来了一个重要的限制:在被动事件监听器中调用event.preventDefault()将无效,并且在开发模式下可能会抛出警告或错误,提示“Unable to preventDefault inside passive event listener”。

当我们的应用场景需要阻止页面的默认滚动行为(例如,实现自定义的缩放、平移或特定的滚动区域)时,默认的onWheel事件监听器就无法满足需求。为了实现对滚轮事件的完全控制并允许阻止其默认行为,我们需要显式地注册一个非被动式(active)的滚轮事件监听器。

实现非被动式滚轮事件监听

CxJS提供了一种灵活且健壮的方法来解决这一限制,即结合使用组件的onRef属性和cx/util模块中的addEventListenerWithOptions方法。

1. 获取目标DOM元素的引用

由于我们无法直接通过JSX属性(如<div onWheel={...}>)来配置事件的passive状态,我们需要获取到目标DOM元素的实际引用,然后在其上添加原生的事件监听器。CxJS组件的onRef属性正是为此目的而设计。它接受一个回调函数作为值,当组件渲染并其对应的DOM元素可用时,该DOM元素会作为参数传递给这个回调函数。

<div onRef='addElementListener'>
  {/* 此div内的内容 */}
</div>
登录后复制

在这里,addElementListener将是我们在CxJS组件类中定义的一个方法,它会在div元素被创建并挂载到DOM时被调用。

2. 使用addEventListenerWithOptions添加非被动式监听器

cx/util模块提供了一个名为addEventListenerWithOptions的实用函数,它封装了原生Element.prototype.addEventListener,并允许我们方便地传递事件选项,包括passive状态。

听脑AI
听脑AI

听脑AI语音,一款专注于音视频内容的工作学习助手,为用户提供便捷的音视频内容记录、整理与分析功能。

听脑AI378
查看详情 听脑AI

首先,您需要在组件文件中导入这个函数:

import { addEventListenerWithOptions } from 'cx/util';
登录后复制

接下来,在您的CxJS组件类中定义addElementListener方法。这个方法将负责在接收到DOM元素时,添加我们的非被动式滚轮事件监听器,并确保其生命周期得到妥善管理。

// 假设这是您的CxJS组件类内部
class MyComponent extends Widget {
    // 用于存储取消订阅函数的变量,以便在组件更新或卸载时清理旧的监听器
    unsubscribeScroll: () => void; 

    /**
     * onRef回调函数,当目标DOM元素可用时被调用。
     * @param {Element} el - 目标DOM元素。
     */
    addElementListener(el: Element) {
        // 在添加新的监听器之前,如果存在旧的监听器,先将其移除。
        // 这对于处理组件更新或重新渲染的情况至关重要,防止重复添加和内存泄漏。
        if (this.unsubscribeScroll) {
            this.unsubscribeScroll();
        }

        // 如果元素不存在(例如,组件正在卸载),则直接返回
        if (!el) {
            return;
        }

        // 使用addEventListenerWithOptions添加非被动式滚轮事件监听器
        this.unsubscribeScroll = addEventListenerWithOptions(
            el,             // 第一个参数:目标DOM元素
            'wheel',        // 第二个参数:事件类型,注意是原生DOM事件名称 'wheel'
            (e: WheelEvent) => { // 第三个参数:事件处理函数
                e.preventDefault(); // 在这里,preventDefault()将正常工作,阻止默认滚动
                // 在此处添加您的自定义滚轮逻辑,例如:
                // console.log('滚轮事件触发,阻止了默认滚动。DeltaY:', e.deltaY);
                // 根据e.deltaY的值实现自定义缩放、滚动或其他交互
            },
            { passive: false } // 第四个参数:事件选项,关键是设置 passive: false
        );
    }

    /**
     * 组件生命周期方法:在组件即将被销毁时调用。
     * 确保在此处移除事件监听器,以防止内存泄漏。
     */
    onDestroy() {
        if (this.unsubscribeScroll) {
            this.unsubscribeScroll();
        }
    }
}
登录后复制

在上述代码中:

  • 我们声明了一个unsubscribeScroll变量来存储addEventListenerWithOptions返回的取消订阅函数。这个函数在被调用时会移除对应的事件监听器,对于管理事件监听器的生命周期至关重要。
  • 在addElementListener方法内部,我们首先检查并移除任何可能存在的旧监听器,以妥善处理组件的更新和重新渲染。
  • addEventListenerWithOptions的第三个参数是我们的事件处理函数,其中我们可以安全地调用e.preventDefault()。
  • 最关键的是第四个参数 { passive: false },它明确告诉浏览器这是一个非被动式监听器,允许我们阻止默认行为。
  • onDestroy生命周期方法用于确保当组件被销毁时,事件监听器也会被正确移除,避免潜在的内存泄漏。

完整示例

将上述代码片段整合到一个完整的CxJS组件中,即可实现一个带有非被动式滚轮事件监听器的div。

import { Widget, VDOM } from 'cx/ui';
import { addEventListenerWithOptions } from 'cx/util';

// 定义一个CxJS组件,用于演示非被动式滚轮事件
class CustomScrollDiv extends Widget {
    // 用于存储取消订阅函数的变量
    unsubscribeScroll: () => void; 

    /**
     * onRef回调函数,当目标DOM元素可用时被调用。
     * @param {Element} el - 目标DOM元素。
     */
    addElementListener(el: Element) {
        // 清理旧的监听器,防止重复添加和内存泄漏
        if (this.unsubscribeScroll) {
            this.unsubscribeScroll();
        }

        // 如果元素不存在(例如,组件正在卸载),则直接返回
        if (!el) {
            return;
        }

        // 添加非被动式滚轮事件监听器
        this.unsubscribeScroll = addEventListenerWithOptions(
            el,
            'wheel',
            (e: WheelEvent) => {
                e.preventDefault(); // 阻止默认的页面滚动行为
                console.log('自定义滚轮事件触发,阻止了默认滚动。DeltaY:', e.deltaY);
                // 在这里添加您的自定义逻辑,例如:
                // if (e.deltaY < 0) {
                //     // 向上滚动逻辑
                // } else {
                //     // 向下滚动逻辑
                // }
            },
            { passive: false } // 关键选项:将事件设置为非被动式
        );
    }

    /**
     * 组件生命周期方法:在组件即将被销毁时调用。
     * 确保在此处移除事件监听器,以防止内存泄漏。
     */
    onDestroy() {
        if (this.unsubscribeScroll) {
            this.unsubscribeScroll();
        }
    }

    render() {
        // 渲染一个带有onRef属性的div
        return (
            <div
                onRef='addElementListener' // 将addElementListener方法绑定到div的onRef属性
                style={{
                    width: '300px',
                    height: '200px',
                    border: '2px solid #4CAF50',
                    overflow: 'auto', // 确保该div本身有滚动条以观察效果
                    padding: '20px',
                    backgroundColor: '#e8f5e9',
                    borderRadius: '8px',
                    boxShadow: '0 2px 4px rgba(0,0,0,0.1)'
                }}
            >
                <p>请在此绿色边框区域内滚动鼠标滚轮。您会发现页面的默认滚动行为被阻止,同时控制台会输出滚轮事件信息。</p>
                <p>内容1</p><p>内容2</p><p>内容3</p><p>内容4</p><p>内容5</p>
                <p>内容6</p><p>内容7</p><p>内容8</p><p>内容9</p><p>内容10</p>
                <p>内容11</p><p>内容12</p><p>内容13</p><p>内容14</p><p>内容15</p>
            </div>
        );
    }
}

// 您可以在您的CxJS应用中像这样使用这个组件:
// <CustomScrollDiv />
登录后复制

注意事项与最佳实践

  • 清理监听器是关键: 始终确保在组件卸载时,或者在onRef回调因组件重新渲染而再次被调用时,移除旧的事件监听器。addEventListenerWithOptions返回的函数就是为此目的而设计。不清理监听器会导致内存泄漏和潜在的意外行为。
  • 事件类型: 在addEventListenerWithOptions中,您应该使用原生DOM事件名称(例如'wheel'),而不是JSX属性名称(例如'onWheel')。
  • 性能考量: 默认将事件设置为被动是为了优化性能。只有当您确实需要阻止默认行为时,才应使用{ passive: false }。过度使用非被动事件可能会对页面的滚动性能产生负面影响,因为它强制浏览器等待您的事件处理函数执行完毕,才能进行滚动。
  • 浏览器兼容性: 现代浏览器普遍支持passive选项。对于一些旧版浏览器,passive选项可能会被忽略,preventDefault()会正常工作(但可能导致滚动卡顿)。CxJS的addEventListenerWithOptions已经考虑了这些兼容性。

总结

通过巧妙地利用CxJS的onRef属性来获取DOM元素引用,并结合cx/util模块中强大的addEventListenerWithOptions方法,我们可以有效地解决onWheel事件的被动监听限制。这种方法赋予了开发者在需要时精确控制滚

以上就是CxJS中实现非被动式滚轮事件监听与默认行为阻止的教程的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号