 用法、别名与底层原理)
数据可视化【免费下载链接】cytoscape.jsGraph theory (network) library for visualisation and analysis项目地址https://gitcode.com/gh_mirrors/cy/cytoscape.js点击查看免费下载cy.removeListener()是 Cytoscape.js 核心实例core上用于解绑事件监听器的标准 API与集合collection上的同名方法共同构成事件生命周期管理的关键环节。本文以官方文档 documentation/md/core/removeListener.md 为骨架结合 src/core/events.mjs 与 src/emitter.mjs 的源码实现系统讲解移除监听器的完整用法、参数语义、事件命名空间保护机制以及测试用例所验证的边界行为帮助你写出无泄漏、可预测的事件代码。一、removeListener 的两种核心用法在核心实例上cy.removeListener()支持两种典型调用方式移除某个事件类型下的全部处理器以及仅移除某个具体处理器。1.1 移除某事件类型的所有处理器cy.on(tap, function(){ /* ... */ }); // 移除所有 tap 监听处理器包括上面注册的那个 cy.removeListener(tap);只要传入事件类型字符串如tap、click、layoutstop即可将该事件下注册的全部处理器一次性解绑。这一形式适合重置某个交互行为例如在视图切换、组件销毁时确保旧的 tap 逻辑不再触发。1.2 仅移除某一个具体处理器var handler function(){ console.log(called handler); }; cy.on(tap, handler); var otherHandler function(){ console.log(called other handler); }; cy.on(tap, otherHandler); // 仅移除 handler保留 otherHandler cy.removeListener(tap, handler);此时需要持有注册时的函数引用即变量handlerremoveListener会通过引用相等精确匹配并移除该处理器其他处理器不受影响。注意如果当初传入的是匿名函数function(){ ... }则无法在之后单独移除它——因此需要单独解绑的监听器务必保存函数引用。二、方法签名与参数语义从 src/core/events.mjs 的源码可见removeListener: function( events, selector, callback ){ this.emitter().removeListener( events, argSelector(selector), callback ); return this; }参数类型含义可选性eventsString | Array事件类型名如tap也支持空格分隔的多个事件如tap click或数组甚至通配符*必填selectorString | Selector委托选择器仅移除绑定在该选择器上的处理器可选callbackFunction要移除的具体处理器函数引用可选与cy.on(events, selector, callback)完全对称传入selector时限定匹配范围传入callback时精确到单个函数。三者组合可精确控制移除粒度。argSelector会把字符串参数解析为内部的Selector实例从而在比较时调用selector.sameText()进行语义比较见 src/core/events.mjs。三、别名体系off / unbind / unlistenremoveListener并不是唯一的名字。在 src/define/events.mjs 中Cytoscape.js 为事件 API 建立了完整的别名矩阵p.addListener p.listen p.bind p.on; p.unlisten p.unbind p.off p.removeListener; p.trigger p.emit;也就是说以下四种写法完全等价cy.removeListener(tap, handler); cy.off(tap, handler); // 最常见的简写 cy.unbind(tap, handler); cy.unlisten(tap, handler);在阅读社区代码或历史项目时cy.off()出现频率最高其行为与removeListener()完全一致。此外还有一个特殊方法cy.removeAllListeners()用于移除全部监听器其实现本质是removeListener(*)见 src/emitter.mjs。四、结合 on() 的配对使用场景4.1 核心上的委托监听与移除removeListener最常见的配对对象是cy.on()。由于元素事件会冒泡到核心见 documentation/md/events.md核心上的委托监听可以覆盖未来才加入的元素。对应的移除方式如下示例改写自 documentation/md/core/on.md// 委托监听冒泡上来的、匹配 node 选择器的 tap 事件 cy.on(tap, node, function(evt){ var node evt.target; console.log(tapped node.id()); }); // 方式一移除所有 node 委托处理器 cy.removeListener(tap, node); // 方式二只移除某个具体的委托处理器 var handler function(evt){ console.log(tapped evt.target.id()); }; cy.on(tap, node, handler); cy.removeListener(tap, node, handler);测试用例 test/events.mjs 专门验证了带选择器的移除cy.off(foo, node, handler)与cy.off(foo, node)均能正确解绑且事件源限定为#n1节点时不再触发。其中 issue #1980 的回归用例test/events.mjs还确认当同一事件上同时存在非委托处理器与委托处理器时cy.off(foo, node, b)只移除委托的那个不会误伤非委托处理器。4.2 集合上的移除集合collection同样拥有removeListener用法与核心一致见 documentation/md/collection/removeListener.mdvar j cy.$(#j); var handler function(){ console.log(tap) }; j.on(tap, handler); j.on(tap, function(){ console.log(some other handler); }); j.emit(tap); // 输出 tap 与 some other handler // 移除引用的 handler j.removeListener(tap, handler); j.emit(tap); // 只剩 some other handler // 移除全部 tap 监听器包括匿名的那一个 j.removeListener(tap);需要特别注意的是集合事件只绑定到调用时已存在的元素见 documentation/md/collection/on.md因此集合上的removeListener也只作用于当前集合中的元素若元素是动态添加的请改用核心上的委托监听 cy.removeListener()。五、源码级原理匹配规则与安全性保障5.1 四重匹配条件Emitter.prototype.removeListenersrc/emitter.mjs采用倒序遍历监听器数组逐条判断是否命中if( ( listener.type type || events * ) ( (!namespace listener.namespace ! .*) || listener.namespace namespace ) ( !qualifier || self.qualifierCompare( listener.qualifier, qualifier ) ) ( !callback || listener.callback callback ) ){ listeners.splice( i, 1 ); return false; }四个条件依次是事件类型listener.type type或传入*表示匹配一切类型命名空间!namespace listener.namespace ! .*或两者相等详见下节选择器未传qualifier则不过滤传入则通过qualifierCompare核心场景下为selector.sameText()做语义比较回调引用未传callback则不过滤传入则要求引用严格相等。由于条件 3、4 在缺省时直接放行所以removeListener(tap)会移除所有 tap 处理器而removeListener(tap, handler)只移除这一个。5.2 命名空间的防误删保护事件字符串支持type.namespace形式如tap.foo内部通过正则^([^.])(\.(?:[^.]))?$解析src/emitter.mjs。Cytoscape.js 定义了一个特殊的通配命名空间*其内部值为universalNamespace .*专门用于匹配任意命名空间但不允许被无命名空间的调用误删。测试 test/events.mjs 验证了这一保护先注册cy.on(foo, lis1)与cy.on(foo.*, lis2)随后执行cy.removeListener(foo)结果是lis1被移除、lis2依然存活。同理removeAllListeners()即removeListener(*)也会保留foo.*这类带通配命名空间的监听器test/events.mjs。这是为了避免开发者在移除普通监听器时意外破坏库内部或第三方扩展依赖的命名空间监听器——如果你的监听器不想被批量移除误伤请使用foo.*形式的命名空间注册。5.3 事件派发中移除的安全处理在监听器回调内部调用off()是常见的自清理模式例如执行一次后自毁。Emitter通过this.emitting计数器感知当前是否处于派发中src/emitter.mjsif( this.emitting ! 0 ){ this.listeners util.copyArray( this.listeners ); }即派发期间先复制监听器数组再修改避免 splice 破坏正在遍历的数组导致跳项或越界。测试 test/events.mjs 验证了在回调中off再on同一个回调时触发次数恰好为 2不会产生多余的重复触发。5.4 promiseOn 的自动清理cy.promiseOn()别名cy.pon()在 src/define/events.mjs 中实现它内部在事件触发后会自动调用self.off.apply(...)移除临时回调因此通过promiseOn注册的监听器无需手动removeListener清理天然避免泄漏。六、实战注意事项小结匿名函数无法单独移除需要精确解绑时把函数保存为变量再传入removeListener。移除粒度由参数决定只传事件类型全部移除传事件选择器按委托范围移除传事件函数精确移除三者也可两两组合。集合与核心的差异集合上的事件只绑定到调用时已存在的元素动态元素请用核心委托监听并用cy.removeListener(events, selector, ...)移除。命名空间是保护伞用事件.*注册的监听器不会被无命名空间或*的移除调用误删反之批量清理前要确认目标监听器是否带命名空间。内存管理在组件销毁、实例弃用前调用cy.removeAllListeners()可快速释放全部监听实例级方法cy.destroy()也会触发destroy事件见 documentation/md/events.md。在回调内移除是安全的Emitter的数组复制机制保证了派发中修改监听器列表不会破坏遍历但应避免过度频繁的 off/on 操作。七、相关资源官方 API 文档documentation/md/core/removeListener.md、documentation/md/collection/removeListener.md配对注册方法documentation/md/core/on.md、documentation/md/collection/on.md事件类型与事件对象字段documentation/md/events.md核心实现src/core/events.mjs、src/emitter.mjs、src/define/events.mjs测试验证test/events.mjscy.off()与eles.off()两个 describe 块赞分享数据可视化【免费下载链接】cytoscape.jsGraph theory (network) library for visualisation and analysis项目地址https://gitcode.com/gh_mirrors/cy/cytoscape.js点击查看免费下载相关推荐Cytoscape.js 集合事件监听器移除eles.removeListener() 方法详解与源码解析Cytoscape.js 集合事件监听器移除eles.removeListener 方法详解与源码解析 导读 在 Cytoscape.js 中 eles.r数据可视化彻底解决Glide内存泄漏事件监听移除实战指南彻底解决Glide内存泄漏事件监听移除实战指南 你是否遇到过Android应用滑动卡顿、频繁崩溃90%的图片加载相关内存泄漏都源于监听器未正确移除。本文将用移动开发缓存图像处理Cytoscape.js 集合一次性事件监听 eles.once() 完全指南用法、与 one 的区别及源码原理Cytoscape.js 集合一次性事件监听 eles.once 完全指南用法、与 one 的区别及源码原理 导读 在 Cytoscape.js 中 ele数据可视化创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考