mint-ui / mint-loadmore

A two-direction mobile load-more component for vue.js
MIT License
315 stars 102 forks source link

iOS使用fastclick的情况下,下拉刷新会触发点击事件 #27

Open Mywifi opened 7 years ago

Mywifi commented 7 years ago

在iOS平台使用fastclick来解决延迟问题,但是在下拉刷新、上拉加载下一页,都会触发列表项目的点击事件,导致进入详情页了,这个如何解决?

uncleLian commented 7 years ago

在mint-ui源码 找到loadmore 相关代码 ,在handleTouchEnd 里面加上event.preventDefault(); event.stopPropagation(); 可以解决这个问题

victorylin commented 7 years ago

使用loadmore组件时,手势横向滑屏,稍微倾斜就会触发下拉更新。如何控制手势的方向,让用户只有比较明显的下拉手势时,才触发下拉更新。请帮忙解答一下,谢谢。

uncleLian commented 7 years ago

踩过坑的我,就帮忙解答一下吧。需要修改源码,方法1:在mint-ui.common.js找到loadmore组件相关代码,在handleTouchMove方法里 (2894行)把distance > 0 ? 'down' : 'up' 数值更改。 方法2:如果同时有上下左右的滑动,建议在源码增加一个属性,用于左右滑动(我左右滑动用的是vue-awsome-swiper)回调中禁止下拉。该下拉组件在IOS端因为-webkit-overflow-scrolling: touch;存在冲突造成无法下拉。fastclick问题的回答,发现在QQ内置打开网页还是存在问题。 image

victorylin commented 7 years ago

@uncleLian 方法2:如果同时有上下左右的滑动,建议在源码增加一个属性,用于左右滑动(我左右滑动用的是vue-awsome-swiper)回调中禁止下拉。针对方法2,有代码可以参考一下么,谢谢了。

bigy6241 commented 7 years ago

@uncleLian 你好可是我完成了修改但是没有生效,,请问这是为什么!

uncleLian commented 7 years ago

@bigy6241 @victorylin 基于Loadmore组件的一些问题,我花了点时间,写了篇博文集中总结一下,可以看看。如还有其他问题,请详细列出,可以帮忙看看。http://liansixin.win/2017/08/01/mint-ui/

bigy6241 commented 7 years ago

我遇到了一个悲伤 的问题,就是修改源码不生效,npm 5.0 后来我就吧mint-ui从node_modules中考到本地修改common.js . 然后咋修改的时候e.preventDefault 和 e.stopPropagation()添加在touchend事件的判断中

var distance = (this.currentY - this.startY) / this.distanceIndex;
      var distanceX = (this.currentX - this.startX) / this.distanceIndex;
      if (this.direction === 'down' && this.getScrollTop(this.scrollEventTarget) === 0 && this.translate > 0) {
        e.preventDefault();
        e.stopPropagation(); 
        this.topDropped = true;
        if (Math.abs(distanceX) < 100 && Math.abs(distance) > 5 &&this.topStatus === 'drop') {
          this.translate = '0';
          this.topStatus = 'loading';
          this.topMethod();
        } else {
          this.translate = '0';
          this.topStatus = 'pull';
        }
      }
      if (this.direction === 'up' && this.bottomReached && this.translate < 0) {
        e.preventDefault();
        e.stopPropagation(); 
        this.bottomDropped = true;
        this.bottomReached = false;
        if (Math.abs(distanceX) < 100 && Math.abs(distance) > 5 &&this.bottomStatus === 'drop') {
          this.translate = '0';
          this.bottomStatus = 'loading';
          this.bottomMethod();
        } else {
          this.translate = '0';
          this.bottomStatus = 'pull';
        }
      }

因为我这里在测试的时候直接放在touchend中的时候会直接吧fastclick的所有事件都阻止掉

baskinwind commented 7 years ago

我也碰到这个坑了,但是也有不用改源码的方式。

因为滚动触发了 touch 事件,而 fastclick 会将 touch 事件转换为 click ,所以出现了滚动时触发了元素的 touch 事件,转而触发了 click ,而想要触发一个元素的正真 click 事件,给元素加上class="needsclick" 就可以了,所以有下面的解决思路: 在会触发点击的元素内盖上一层元素,点击事件在这个盖的元素上处理,然后给这个元素加上 class="needsclick" (只要元素加上这个 class 这个元素上的点击事件就是正常的 click 也就不会因为 touch 事件而触发 click 处理函数了)

dom 结构大概是这样

div.box1
    div.needsclick @click=‘handleClick’
    div.content

box1 为最外层元素 position: relative; needsclick 为覆盖元素 position: absolute; 大小与 box1 一致完全的覆盖在 content 元素上 content 为内容

写在最后:在 box1 上加 needsclick 是不起作用的,因为当滑动的时候我们不是在 box1 上触发了 touch 而是它的子元素,所以在 box1 上监听 click 其实处理的它子元素冒泡上来的 touch 事件(而 touch 事件已经被处理成了 click ),即使 box1 上触发的是真正的 click 事件,所以才有了覆盖的那一层,当然我们可以给每个 box1 下的内容都加上 class="needsclick" 但这个体验感觉不是很好,应该也是行的通的,但一想到 box1 下面的元素之多(而且基本上仅仅是为了显示),我想想还是算了。

所以才有了这个方案:所有的点击都触发在覆盖元素的那一层,而 content 元素永远都点击不到,因为覆盖元素的点击事件是真正的 cilck 所以也就不存在了因为 touch 事件而触发的 click 了,问题算是半完美解决,因为这会导致 content 中的内容不能点,这算是一个小 bug ,但完美的方法也说了就是给每个 box1 中的元素都加上 class="needsclick" 根据需求加吧。

lyh2668 commented 7 years ago

@acccco 你的思路可以结合derectives解决

Ninnka commented 6 years ago

@uncleLian 其实通过加大distance的临界值来判断是不太合适的,我认为应该判断滑动的角度来判断是应该垂直滑动还是水平滑动。我修改代码的步骤是这样的: 1.在handleTouchStart方法中,加入

this.startX = event.touches[0].clientX;

2.在handleTouchMove方法中,修改为

this.currentY = event.touches[0].clientY;
this.currentX = event.touches[0].clientX;
const diffX = this.currentX - this.startX;
const diffY = this.currentY - this.startY;
if (Math.abs(diffX) / Math.abs(diffY) > Math.tan(30 * Math.PI/180)) {
  return;
}

此外,我是修改lib/loadmore/index.js文件后才生效的