在小程序中,通过设置bindtap 属性,就能绑定点击事件
// wxml <view bindtap="bindTap">点我</view>
// js bindTap: function(e) { console.log("点击"); }
上面简单实现了单击事件的绑定
同样,长按事件的绑定也很简单
// wxml <view bindlongtap="bindLongTap">长按我</view>
// js bindLongTap: function(e) { console.log("长按"); }
根据文档,手指触摸后,超过350ms再离开就会执行长按事件
看上面的demo,好像没有什么毛病,实现起来非常简单
但是,在实际开发的过程中,比如说微信的对话界面,点击的时候需要打开对话界面,而长按的时候需要弹出一个菜单(ios滑动另说,小程序中没有列表滑动api),这时候就需要同时处理点击和长按事件
你可能会说,同时绑定bindtap 和 bindlongtap 事件不就好了吗?
// wxml <view bindtap="bindTap" bindlongtap="bindLongTap">撸我</view>
// js bindTap: function(e) { console.log("点击"); } bindLongTap: function(e) { console.log("长按"); }
运行之后,你会发现,会先执行“长按”后,紧接着松开的时候会执行“点击”
看个演示
上面例子中,长按事件会显示一个菜单,而点击事件则是跳转到编辑界面,明显这里有事件冲突了
通过测试,我们发现,小程序中事件执行的顺序是
点击:touchstart → touchend → tap
长按 touchstart → longtap → touchend → tap
可以发现,实际上每个事件,最后都会去执行tap事件
这tm就尴尬了,看来正常的事件绑定是行不通了
根据事件执行的顺序,touchstart、touchend 和 tap 事件是必须执行的,在看看长按执行的条件
手指触摸后,超过350ms再离开
那么我们是不是可以自己来实现长按呢?
通过touchstart 和 touchend 的时间节点,来判断是点击还是长按
// wxml <view bindtouchstart="bindTouchStart" bindtouchend="bindTouchEnd" bindtap="bindTap">蹂躏我</view>
// js bindTouchStart: function(e) { this.startTime = e.timeStamp; } bindTouchEnd: function(e) { this.endTime = e.timeStamp; } bindTap: function(e) { if(this.endTime - this.startTime > 350) { console.log("长按"); } else { console.log("点击") } }
看下实际项目中的例子
你会发现这样做的话,菜单的弹出会在松手之后,这样体验不太好,所以长按事件我们还必须保留
// wxml <view bindtouchstart="bindTouchStart" bindtouchend="bindTouchEnd" bindlongtap="bingLongTap" bindtap="bindTap">蹂躏我</view>
// js bindTouchStart: function(e) { this.startTime = e.timeStamp; } bindTouchEnd: function(e) { this.endTime = e.timeStamp; } bindTap: function(e) { if(this.endTime - this.startTime < 350) { console.log("点击") } } bingLongTap: function(e) { console.log("长按"); }
看一下
比较完美的解决了
对于事件传递小程序还有待加强,可以类似android那样控制事件是否继续往下传递就好了
如果您有更高的方法,请告诉我