在混合开发中,h5页面作为一个单独页面,也可以内嵌到客户端的组件中,因为webview本身也属于一种客户端组件。
最常见的如,在多Tab切换布局中,某些页面可能是内嵌Webview,使用H5渲染。
那么这种场景带来的问题是,如果H5页面内也存在Tab切换,客户端的Tab滑动切换和H5的滑动切换事件如何切换,如下图:
当H5处于第二页,右滑在H5内切换
当H5处于第一页,右滑切换到原生
先看一下Android的事件响应机制,如下图
组件中提供了dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent方法,通过重写以上方法返回true,false 判断组件是否分发,拦截,消费事件。
看着比较复杂,但是基本逻辑和H5的捕获冒泡流程类似,只是功能更加完整一些。
所以,当事件传递到原生层时,原生层会传递到Webview层,如果Webview层阻止或消费掉事件,事件将不会冒泡到上层原生层组件,明白了思路后看一下如何实现。
简单代码如下:
<!--监听touchmove,touchstart实现滑动切换 -->
<div class="swiper-container" @touchmove="touchmove" @touchstart="touchstart">
<div :style="{ transform: 'translateX(' + translateX + 'px)' }">
</div>
</div>
touchstart(event) {
this.clientX = event.touches[0].clientX;
this.tickCnt = 0;
this.direction = '';
this.lastClientX = 0;
},
touchmove(event) {
this.tickCnt++;
// 在前几个滑动tick中,使用preventDefault(),阻止事件向上传递到组件层
if (this.tickCnt < 4) {
event.preventDefault();
return;
}
// 判断是左滑还是右滑
var clientX = event.touches[0].clientX;
if (this.tickCnt >= 4 && !this.direction) {
if (clientX - this.clientX < 0) {
this.direction = 'L';
} else {
this.direction = 'R';
}
}
// 下面我们就可以通过左滑和右滑,判断是H5去切换,或者是不消费事件,使事件继续向上层原生组件传递
//左滑,h5滑动切换,并且preventDefault()阻止事件向上传递
if (this.direction == 'L') {
if (!this.lastClientX) {
this.lastClientX = clientX;
}
this.move(clientX);
event.preventDefault();
}else{
//右滑,不处理,H5不消费,事件向上传递,原生去消费
}
},
move(clientX) {
let diff = clientX - this.lastClientX;
this.translateX = diff;
},