zoukankan      html  css  js  c++  java
  • zepto.js中的Touch事件

      在移动端经常需要处理滑动事件,比如banner图的左滑右滑,都需要事件响应,这在PC端是没有这类事件的。而在zepto.js中,下载下来的代码也并没有自动加上对这类事件的支持,但是有提供相应的模块,需要你自己加上去(下表中最后一个touch模块):

    moduledefaultdescription
    zepto 核心模块;包含许多方法
    event 通过on()off()处理事件
    ajax XMLHttpRequest 和 JSONP 实用功能
    form 序列化 & 提交web表单
    ie 增加支持桌面的Internet Explorer 10+和Windows Phone 8。
    detect   提供 $.os和 $.browser消息
    fx   The animate()方法
    fx_methods   以动画形式的 showhidetoggle, 和 fade*()方法.
    assets   实验性支持从DOM中移除image元素后清理iOS的内存。
    data   一个全面的 data()方法, 能够在内存中存储任意对象。
    deferred   提供 $.Deferredpromises API. 依赖"callbacks" 模块. 
    当包含这个模块时候, $.ajax() 支持promise接口链式的回调。
    callbacks   为"deferred"模块提供 $.Callbacks
    selector   实验性的支持 jQuery CSS 表达式 实用功能,比如 $('div:first')el.is(':visible')
    touch   在触摸设备上触发tap– 和 swipe– 相关事件。这适用于所有的`touch`(iOS, Android)和`pointer`事件(Windows Phone)。

      这些模块的代码可以直接加在zepto.js的最底部,像拼积木一样,选择模块然后加上去拼合一份适合自己项目的加强版zepto.js。

      关于代码中是如何实现的事件这里不做过多解读,核心肯定是通过touch坐标的差值判断到底是左滑还是上滑。这里主要讲的是touch模块中的一个坑,那就是会和国内的主流手机浏览器的默认事件冲突。具体表现就是,给一个元素绑定左滑动后,在UC浏览器中滑动该元素会出现页面被切换的情况。

      简单的测试发现:UC/QQ都与touch事件发生冲突,安卓自带浏览器和谷歌浏览器不会有此现象。touch这个脚本本来就是外国人写的,当然就无视中国特色了。这里对touch做了一些简单的修改,达到避免这种冲突发生。

      首先引入zepto(已包含touch)之后,代码如下:  

    $('#div').swipeLeft(function(e){
         alert(1);	  	 
    })
    

      在PC上用谷歌开发工具模拟器看,没有任何问题。

      在手机上用UC或者QQ看,悲催了,页面直接被滑跑了。你可以试试,体验一下总比别人告诉你印象深刻。

      很明显,这里需要阻止默认事件,比如这样改一改:  

    $('#div').on('touchstart',function(e){
       e.preventDefault();
    }).swipeLeft(function(e){
       alert(1);	  	 
    })
    

      手机上便可以弹出1。然后事情并没有结束。

      首先这样写太丑陋了,每个swipe之前都要去阻止默认事件,更加难以接受的是,这个时候我上下滑动该元素也会阻止默认事件,也就意味着,当页面需要正常上下滚动的时候,手指在该元素上将滑动不了!

      好吧,那我就去改touch。

      首先,找到touch事件快捷绑定的代码块:  

    ;['swipe', 'swipeLeft', 'swipeRight', 'swipeUp', 'swipeDown', 'doubleTap', 'tap', 'singleTap', 'longTap'].forEach(function(m){
        $.fn[m] = function(callback){  
          return this.bind(m, callback) 
        }
    })
    

      修改如下:

    ;['swipe', 'swipeLeft', 'swipeRight', 'swipeUp', 'swipeDown', 'doubleTap', 'tap', 'singleTap', 'longTap'].forEach(function(m){
        $.fn[m] = function(callback){  
          if(!this.data('swipeEvents')){
            this.data('swipeEvents',m);
          }else{
            this.data('swipeEvents',this.data('swipeEvents')+'|'+m);
          }       
          return this.bind(m, callback) 
        }
    })
    

      目的:给所有直接调用swipe的元素,默默的标识上一个数据,该数据就是本元素被绑定的swipe事件的名称,绑定多个swipe时以 | 隔开。

      第二步:找到给body绑定的事件冒泡的touchmove事件代码:

    .bind('touchmove', function(e){
          cancelLongTap()
          touch.x2 = e.touches[0].pageX
          touch.y2 = e.touches[0].pageY
    })
    

      修改为:

    .bind('touchmove', function(e){
          cancelLongTap()
          touch.x2 = e.touches[0].pageX
          touch.y2 = e.touches[0].pageY
          
          if(touch.el&&touch.el.data('swipeEvents')){  
            if(Math.abs(touch.x2-touch.x1)>4&&/Left|Right/.test(touch.el.data('swipeEvents'))){
              e.preventDefault();
            }else if(Math.abs(touch.y2-touch.y1)>4&&/Up|Down/.test(touch.el.data('swipeEvents'))){
              e.preventDefault();
            }
          }      
     })
    

      目的:只要该元素绑定了swipe事件,并且滑动轨迹和swipe事件匹配上,则阻止默认事件。这样,匹配不上的将不被阻止,比如你只是绑定的左右滑动,当touch是上下滑动的时候,不会执行到preventDefault。

      经过UC和QQ测试都没有问题。

      但是,事情还是没有结束。因为,你只要换个方式绑定swipe就挂了,比如这样子:  

    $('#div').on('swipeLeft',function(e){
    

      因为我们只给$.fn[swipe]的时候做了处理,也就是元素直接调用siwpe方法时,才会有效,一旦调用on方法就嗝屁了。当然,一般元素直接调用swipe就可以了,但是如果想用到事件委托,给大量元素批量绑定的时候就必须用到on啊,这怎么办?不好意思,我这里没有给出好办法,因为on这个方法不好改也不能改,改touch已经是心惊胆战了,直接改zepto水平不够。所以暂时还没想到最好的办法,谁知道完美解决办法的请留言。

       

  • 相关阅读:
    从零开始学VUE之组件化开发(组件数据的存放)
    从零开始学VUE之组件化开发(组件分离写法)
    从零开始学VUE之组件化开发(语法糖优化组件注册)
    进程与线程的一个简单解释
    Crontab爬虫定时执行
    接口分类复习
    最长公共子串
    最长公共子序列(力扣第1143题)
    Reduce端分组排序源码分析
    Job提交流程源码和切片源码详解
  • 原文地址:https://www.cnblogs.com/webLilingyun/p/5542283.html
Copyright © 2011-2022 走看看