Skip to content

跨端能力增强 ​

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 一致的事件语义。

兼容说明 ​

若个别平台 / 事件仍无法动态阻止冒泡,可在子级处理里打标记、父级读取标记并跳过,达到等效效果。