0

0

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

碧海醫心

碧海醫心

发布时间:2025-11-01 15:18:00

|

302人浏览过

|

来源于php中文网

原创

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属性(如

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

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

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

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

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

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 (
            

请在此绿色边框区域内滚动鼠标滚轮。您会发现页面的默认滚动行为被阻止,同时控制台会输出滚轮事件信息。

内容1

内容2

内容3

晓语台
晓语台

晓语台,是一款AI文本创作产品。创作能力主要围绕营销文本的AI创作,晓语台覆盖了品牌与市调、商业媒体、社交媒体、搜索营销、数字广告、职场办公共六类全营销文本

下载

内容4

内容5

内容6

内容7

内容8

内容9

内容10

内容11

内容12

内容13

内容14

内容15

); } } // 您可以在您的CxJS应用中像这样使用这个组件: //

注意事项与最佳实践

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

总结

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

相关专题

更多
DOM是什么意思
DOM是什么意思

dom的英文全称是documentobjectmodel,表示文件对象模型,是w3c组织推荐的处理可扩展置标语言的标准编程接口;dom是html文档的内存中对象表示,它提供了使用javascript与网页交互的方式。想了解更多的相关内容,可以阅读本专题下面的文章。

2624

2024.08.14

DOM是什么意思
DOM是什么意思

dom的英文全称是documentobjectmodel,表示文件对象模型,是w3c组织推荐的处理可扩展置标语言的标准编程接口;dom是html文档的内存中对象表示,它提供了使用javascript与网页交互的方式。想了解更多的相关内容,可以阅读本专题下面的文章。

2624

2024.08.14

JavaScript ES6新特性
JavaScript ES6新特性

ES6是JavaScript的根本性升级,引入let/const实现块级作用域、箭头函数解决this绑定问题、解构赋值与模板字符串简化数据处理、对象简写与模块化提升代码可读性与组织性。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

0

2025.12.24

php框架基础知识汇总
php框架基础知识汇总

php框架是构建web应用程序的架构,提供工具和功能,以简化开发过程。选择合适的框架取决于项目需求和技能水平。实战案例展示了使用laravel构建博客的步骤,包括安装、创建模型、定义路由、编写控制器和呈现视图。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1

2025.12.24

Word 字间距调整方法汇总
Word 字间距调整方法汇总

本专题整合了Word字间距调整方法,阅读下面的文章了解更详细操作。

2

2025.12.24

任务管理器教程
任务管理器教程

本专题整合了任务管理器相关教程,阅读下面的文章了解更多详细操作。

2

2025.12.24

AppleID格式
AppleID格式

本专题整合了AppleID相关内容,阅读专题下面的文章了解更多详细教程。

2

2025.12.24

csgo视频观看入口合集
csgo视频观看入口合集

本专题整合了csgo观看入口合集,阅读下面的文章了知道更多入口地址。

29

2025.12.24

yandex外贸入口合集
yandex外贸入口合集

本专题汇总了yandex外贸入口地址,阅读下面的文章了解更多内容。

64

2025.12.24

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 2.9万人学习

国外Web开发全栈课程全集
国外Web开发全栈课程全集

共12课时 | 0.9万人学习

React核心原理新老生命周期精讲
React核心原理新老生命周期精讲

共12课时 | 1.0万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

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