Skip to content

事件 API

tui-entine 提供了完整的事件系统,支持触摸事件和点击事件。

事件类型

touchstart

触摸开始事件。当用户手指开始触摸屏幕时触发。

示例:

ts
element.addEventListener("touchstart", (event: ITuiTouchEvent) => {
  console.log("触摸开始", event.clientX, event.clientY);
});

touchmove

触摸移动事件。当用户手指在屏幕上移动时触发。

示例:

ts
element.addEventListener("touchmove", (event: ITuiTouchEvent) => {
  console.log("触摸移动", event.clientX, event.clientY);
});

touchend

触摸结束事件。当用户手指离开屏幕时触发。

示例:

ts
element.addEventListener("touchend", (event: ITuiTouchEvent) => {
  console.log("触摸结束", event.clientX, event.clientY);
});

click

点击事件。当用户快速点击元素时触发(触摸持续时间 < 300ms 且移动距离 < 10px)。

示例:

ts
element.addEventListener("click", (event: ITuiTouchEvent) => {
  console.log("元素被点击", event.clientX, event.clientY);
});

事件对象

事件对象 ITuiTouchEvent 包含以下属性和方法:

属性

属性类型描述
typestring事件类型('touchstart', 'touchmove', 'touchend', 'click')
targetITuiElement触发事件的元素
currentTargetITuiElement当前处理事件的元素
timeStampnumber事件发生的时间戳
nativeEventUniEvent原生事件对象
clientXnumber客户端 X 坐标
clientYnumber客户端 Y 坐标
xnumber触摸点 X 坐标
ynumber触摸点 Y 坐标
pageXnumber页面 X 坐标
pageYnumber页面 Y 坐标
offsetXnumber元素内 X 偏移
offsetYnumber元素内 Y 偏移
changedTouchesITuiTouchEvent[]触摸点数组

方法

方法描述
stopPropagation()停止事件冒泡
preventDefault()阻止默认行为

事件处理

添加事件监听器

使用 addEventListener 方法为元素添加事件监听器:

ts
const listenerId = element.addEventListener("click", (event) => {
  console.log("元素被点击");
});

移除事件监听器

使用 removeEventListener 方法移除事件监听器:

ts
element.removeEventListener(listenerId);

事件冒泡

事件会从触发元素向上冒泡到父元素,除非调用 stopPropagation() 方法阻止:

ts
element.addEventListener("click", (event) => {
  console.log("元素被点击");
  event.stopPropagation(); // 阻止事件冒泡
});

事件委托

利用事件冒泡机制,可以在父元素上监听子元素的事件:

ts
parentElement.addEventListener("click", (event) => {
  console.log("点击了元素:", event.target.id);
});

触摸事件处理

基本触摸处理

ts
function touchstart(e: any) {
  engine.handleTouchEvent(e);
}

function touchmove(e: any) {
  engine.handleTouchEvent(e);
}

function touchend(e: any) {
  engine.handleTouchEvent(e);
}

多点触摸

tui-entine 支持多点触摸,通过 changedTouches 属性可以获取所有触摸点:

ts
element.addEventListener("touchmove", (event) => {
  event.changedTouches.forEach((touch: ITuiTouchEvent) => {
    console.log("触摸点:", touch.x, touch.y);
  });
});

事件最佳实践

1. 及时清理事件监听器

当元素不再需要时,应该移除事件监听器以避免内存泄漏:

ts
// 添加监听器
const listenerId = element.addEventListener("click", handleClick);

// 移除监听器
element.removeEventListener(listenerId);

2. 使用事件委托

对于多个子元素,使用事件委托可以减少事件监听器的数量:

ts
// 为父元素添加一个监听器
parentElement.addEventListener("click", (event) => {
  // 根据 target 判断点击的是哪个子元素
  if (event.target.classList.contains("item")) {
    console.log("点击了项目:", event.target.id);
  }
});

3. 合理使用事件冒泡

利用事件冒泡可以简化事件处理逻辑,但要注意避免不必要的事件传播:

ts
// 子元素
childElement.addEventListener("click", (event) => {
  console.log("子元素被点击");
  // 必要时阻止冒泡
  // event.stopPropagation();
});

// 父元素
parentElement.addEventListener("click", (event) => {
  console.log("父元素被点击");
});

4. 处理触摸和点击

在移动设备上,触摸事件和点击事件可能会同时触发,需要合理处理:

ts
let isTouching = false;

element.addEventListener("touchstart", () => {
  isTouching = true;
});

element.addEventListener("click", () => {
  if (!isTouching) {
    console.log("鼠标点击");
  } else {
    console.log("触摸点击");
  }
  isTouching = false;
});

性能优化

1. 减少事件监听器数量

尽量使用事件委托,减少直接在每个元素上添加监听器。

2. 防抖和节流

对于频繁触发的事件(如 touchmove),可以使用防抖或节流来优化性能:

ts
// 节流函数
function throttle(func: Function, delay: number) {
  let lastCall = 0;
  return function (...args: any[]) {
    const now = Date.now();
    if (now - lastCall >= delay) {
      lastCall = now;
      return func.apply(this, args);
    }
  };
}

// 使用节流处理 touchmove
element.addEventListener(
  "touchmove",
  throttle((event) => {
    console.log("触摸移动", event.clientX, event.clientY);
  }, 16),
); // 约 60fps

3. 避免在事件处理中进行复杂计算

事件处理函数应该尽量简洁,避免执行复杂的计算或 DOM 操作:

ts
element.addEventListener("click", () => {
  // 避免复杂计算
  setTimeout(() => {
    // 复杂操作放在异步中执行
    performHeavyCalculation();
  }, 0);
});

4. 使用 passive 事件监听器

对于不需要阻止默认行为的事件,可以使用 passive 监听器提高性能:

ts
// 注意:tui-entine 目前可能不直接支持 passive 选项
// 但在原生事件处理中可以考虑
window.addEventListener("touchmove", handleTouchMove, { passive: true });

常见问题

1. 点击事件不触发

原因:

  • 元素可能被其他元素遮挡
  • 触摸事件被阻止冒泡
  • 触摸持续时间过长或移动距离过大

解决方案:

  • 检查元素层级和 z-index
  • 确保事件正确传递到引擎
  • 确保触摸操作符合点击事件的触发条件

2. 事件触发多次

原因:

  • 多次添加相同的事件监听器
  • 事件冒泡导致父元素也触发事件

解决方案:

  • 确保只添加一次事件监听器
  • 合理使用 stopPropagation()

3. 触摸事件卡顿

原因:

  • 事件处理函数执行时间过长
  • 频繁的 DOM 操作

解决方案:

  • 优化事件处理函数
  • 使用节流或防抖
  • 减少 DOM 操作,使用局部更新

4. 多点触摸不工作

原因:

  • 没有正确处理 changedTouches
  • 触摸事件没有正确传递

解决方案:

  • 检查触摸事件传递
  • 使用 changedTouches 处理多点触摸