混合App 开发模式下,Web与原生Tab页中,滑动手势事件如何正确分发响应

868 阅读1分钟

在混合开发中,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; 
},