Event DOM 事件工具

GB.Event 是一个零依赖的 DOM 事件工具。它基于浏览器原生 Event API,提供统一的事件绑定、主动触发和移除能力,并用 Pointer Events 同时处理鼠标、触摸与触控笔输入。

快速开始

向 GB.Event() 传入 CSS 选择器或 DOM 元素,再调用事件方法注册监听器。所有绑定方法都会返回当前实例,因此可以连续配置多个事件。

GB.Event('#saveButton')
  .click(event => {
    console.log('保存', event.currentTarget);
  })
  .enter(() => {
    console.log('指针进入按钮');
  });

安装与引入

浏览器直接引入

在业务脚本之前引入,之后即可使用全局方法 GB.Event(target)。

<script src="https://cloud.m775.net/js/event.js"></script>

npm 项目

npm i @gentbo/event

import '@gentbo/event';

选择目标元素

GB.Event(target) 创建并返回一个事件操作实例。target 支持以下三种形式:

CSS 选择器内部按选择器查找元素,例如 GB.Event('#button')。
HTMLElement直接使用已经取得的 DOM 元素。
NodeList接收元素列表,但默认只操作列表中的第一个元素。
const bySelector = GB.Event('#button');

const element = document.querySelector('#button');
const byElement = GB.Event(element);

const elements = document.querySelectorAll('.item');
const firstItem = GB.Event(elements); // 只操作第一个元素

如果需要为列表中的每个元素绑定事件,请主动遍历 NodeList:

document.querySelectorAll('.item').forEach(element => {
  GB.Event(element).click(handleItemClick);
});

通用事件 API

通用方法适用于工具未提供快捷方法的原生事件,也可用于业务自定义事件。

.set(name, callback, once?)绑定指定名称的事件;once 为 true 时监听器只执行一次。
.add(name, callback, once?)set() 的别名,参数与行为完全相同。
.remove(name, callback)移除监听器;callback 必须是绑定时使用的同一个函数引用。
.run(name, detail?)主动触发事件,可通过 detail 传递自定义数据。
.execute(name, detail?)run() 的别名。
.start(name, detail?)run() 的别名。
const button = GB.Event('#button');

button.set('click', event => {
  console.log(event.type);
});

button.run('click');

快捷事件方法

快捷方法的调用形式一致:第一个参数是监听函数,第二个可选参数 once 控制是否只执行一次。

click / click2对应 click / dblclick,用于单击和双击。
menu / wheel对应 contextmenu / wheel,用于右键菜单和滚轮输入。
down / move / up对应 pointerdown / pointermove / pointerup。
enter / leave对应 pointerenter / pointerleave,事件不冒泡。
hover / out对应 pointerover / pointerout,会冒泡,进入或离开子元素时也可能触发。
keyDown / keyUp对应 keydown / keyup。
input / change对应 input / change,用于输入值与选项变化。
focus / blur / select对应 focus / blur / select,用于焦点及文本选择。
imStart / imUpdate / imEnd对应 compositionstart / compositionupdate / compositionend。
submit / reset对应 submit / reset,用于表单提交和重置。
GB.Event('#button').click(event => {
  console.log('只响应第一次点击');
}, true);

优先使用 Pointer Events

Pointer Events 用一套事件统一鼠标、触摸屏和触控笔输入。相比同时维护 mousedown、touchstart 等多套逻辑,更适合跨桌面端和移动端的交互。

const surface = GB.Event('#drawingSurface');

surface
  .down(event => beginDraw(event))
  .move(event => continueDraw(event))
  .up(event => endDraw(event));

enter()/leave() 不冒泡,适合只关心目标元素边界的场景;hover()/out() 会冒泡,指针经过子元素时也可能触发,请根据页面结构选择。

处理文本输入与输入法

input() 会在输入值变化时触发。处理中文、日文等输入法时,可以结合 Composition Events,避免在文字尚未组合完成时过早执行搜索或校验。

let composing = false;
const search = GB.Event('#search');

search
  .imStart(() => {
    composing = true;
  })
  .imEnd(event => {
    composing = false;
    runSearch(event.target.value);
  })
  .input(event => {
    if (!composing) runSearch(event.target.value);
  });

自定义事件与数据传递

先通过 set() 注册自定义事件,再用 run() 触发。传入的对象可从监听器的 event.detail 中读取。

const profile = GB.Event('#profile');

profile.set('user:update', event => {
  console.log(event.detail);
});

profile.run('user:update', {
  id: 100,
  name: 'Gentbo'
});

移除事件监听器

remove() 必须接收绑定时使用的同一个函数引用。匿名函数即使代码相同,也不是同一个函数,无法用于移除原监听器。

function handleClick(event) {
  console.log('click', event);
}

const button = GB.Event('#button');

button.click(handleClick);
button.remove('click', handleClick);

表单示例

监听 submit 时,可使用原生事件对象阻止浏览器默认提交,再执行校验或异步请求。

GB.Event('#loginForm').submit(event => {
  event.preventDefault();

  const formData = new FormData(event.currentTarget);
  submitLogin(formData);
});

使用边界

目标不存在选择器没有匹配到元素时,后续事件绑定无法执行;动态页面应在元素创建后再绑定。
NodeList默认只使用第一个元素;批量绑定时需要自行遍历。
移除监听保留原函数引用,并在组件销毁或页面卸载时移除长期监听器。
原生行为阻止默认行为和停止冒泡仍使用 event.preventDefault() 与 event.stopPropagation()。
const element = document.querySelector('#box');

if (element) {
  GB.Event(element).click(handleClick);
}

兼容性

运行环境需要支持 ES2020、Class Private Field、DOM Event API 和 Pointer Event API。适用于现代 Chrome、Edge、Firefox、Safari,以及微信、支付宝和常见 Chromium 内置浏览器。