从dart:html迁移到package:web后,如何处理onContextMenu事件?
问题
在从dart:html迁移到package:web的过程中,我需要更新一段监听文档右键(上下文菜单)事件的代码。
原dart:html实现代码:
import 'dart:html' as html; html.window.document.onContextMenu.listen((event) {});
尝试迁移到package:web的代码:
import 'package:web/web.dart' as web; web.window.document.onContextMenu.listen((event) {});
运行时触发错误:
The getter 'onContextMenu' isn't defined for the type 'Document'.
请问使用package:web监听文档contextmenu事件的正确方式是什么?如何实现dart:html中onContextMenu的等效功能?
解决方案
package:web的Document类没有提供onContextMenu这类封装好的事件流getter,需要直接调用原生Web API风格的addEventListener方法绑定事件,这和原生JavaScript的事件绑定逻辑完全一致:
基础实现方式
直接使用addEventListener绑定contextmenu事件:
import 'package:web/web.dart' as web; import 'dart:js_interop' as js_interop; void main() { web.document.addEventListener( 'contextmenu', js_interop.allowInterop((web.Event event) { // 阻止默认右键菜单(可选) event.preventDefault(); // 在这里编写你的事件处理逻辑 }), ); }
模拟Stream监听(贴近dart:html使用习惯)
如果习惯dart:html中通过listen监听Stream的方式,可以自己封装一个Stream来适配:
import 'package:web/web.dart' as web; import 'dart:js_interop' as js_interop; import 'dart:async'; final _contextMenuController = StreamController<web.Event>.broadcast(); Stream<web.Event> get documentContextMenuStream => _contextMenuController.stream; void initContextMenuListener() { web.document.addEventListener( 'contextmenu', js_interop.allowInterop((web.Event event) { _contextMenuController.add(event); }), ); } // 使用示例 void main() { initContextMenuListener(); documentContextMenuStream.listen((event) { event.preventDefault(); // 处理事件逻辑 }); }
核心说明
package:web完全对齐原生Web API,事件名称使用小写的contextmenu,和dart:html的驼峰式onContextMenu对应;- 必须通过
js_interop.allowInterop将Dart函数转换为JavaScript可调用的函数,否则无法正常绑定事件; - 如需阻止浏览器默认右键菜单,调用
event.preventDefault()即可,逻辑和原生JS一致。
内容的提问来源于stack exchange,提问作者Reza Farjam
相关产品推荐
相关产品推荐

