跨端能力增强
tui-compiler 在编译期为跨端差异提供了两层增强:Web 端 touchmove 浏览器兼容与小程序事件代理。两者都在编译阶段完成,业务代码不需要写任何平台差异逻辑。
Web 端 touchmove 浏览器兼容
解决的问题
移动端手势(拖拽、滑动、长按滑动)在 Web 端依赖 touchmove,但不同浏览器 / 内核存在差异:
- 部分浏览器
touchmove中touches与changedTouches的取值时机不一致 - 缺少统一的默认行为处理,滑动时页面跟随滚动,导致拖拽 / 滑动手势被打断
- 指针事件(PointerEvent)与触摸事件混用时行为不统一
增强内容
编译器在 Web 平台为触摸事件注入兼容层:
- 统一
touchmove的坐标取值(优先touches,回退changedTouches) - 修正滚动穿透与默认行为处理,保证拖拽 / 滑动手势顺畅
- 抹平浏览器差异,使同一套手势代码在 Chrome / Safari / 微信内置浏览器上表现一致
使用方式
按正常写法监听事件即可,无需额外的平台判断:
vue
<template>
<t-view @touchstart="onTouchStart"
@touchmove="onTouchMove"
@touchend="onTouchEnd">
<slot></slot>
</t-view>
</template>
<script setup>
function onTouchStart(_e : UniTouchEvent) {}
// 浏览器差异由编译器统一处理
function onTouchMove(_e : UniTouchEvent) {}
function onTouchEnd(_e : UniTouchEvent) {}
</script>小程序事件代理
解决的问题
小程序原生事件默认向上冒泡,且无法在 JS 回调里动态阻止;当自定义组件内部又 emit 了同名事件时,父级的同一个处理函数会被触发两次,而 App / Web 端只会触发一次,导致多端行为不一致。
增强内容
编译器在编译期为组件注入「事件代理」:
- 把事件监听统一收口到事件总线
- 自动识别回调里写的
e.stopPropagation(),改写为代理内部的bus.stop('事件名') - 等效于小程序模板里的
catch前缀,但不需要写任何平台差异代码 - 用户端无感:写法与 App / Web 完全一致
事件代理默认开启,可通过 TuiCollector({ eventProxy: false }) 显式关闭。
使用方式
vue
<template>
<view @click="onGrandparent">
<view @click="onParent">
<t-button @click="onChild">点我</t-button>
</view>
</view>
</template>
<script setup>
// App / Web / 小程序:行为完全一致
function onChild(e : UniPointerEvent) {
e.stopPropagation() // 阻断冒泡,父级 / 祖先不再触发
}
function onParent(_e : UniPointerEvent) {}
function onGrandparent(_e : UniPointerEvent) {}
</script>编译后(示意):
e.stopPropagation()会被转换为事件代理的bus.stop('click'),小程序端据此阻断原生冒泡,从而获得与 App / Web 一致的事件语义。
兼容说明
若个别平台 / 事件仍无法动态阻止冒泡,可在子级处理里打标记、父级读取标记并跳过,达到等效效果。