问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

ios的click时间有0.1s的延迟,这个怎么处理

发布网友 发布时间:2022-04-22 18:56

我来回答

2个回答

懂视网 时间:2022-04-22 23:17

这篇文章主要介绍了通过fastclick源码分析彻底解决tap“点透”问题的知识内容,有兴趣的朋友学习一下吧。

近期使用tap事件为老夫带来了这样那样的问题,其中一个问题是解决了点透还需要将原来一个个click变为tap,这样的话我们就抛弃了ie用户

当然可以做兼容,但是没人想动老代码的,于是今天拿出了fastclick这个东西,

这是最近第四次发文说tap的点透事件,我们一直对解决“点透”的蒙版耿耿于怀,于是今天老大提出了一个库fastclick,最后证明解决了我们的问题

而且click不必替换为tap了,于是我们老大就语重心长的对我说了一句,你们就误我吧,我邮件都发出去了......

于是我下午就在看fastclick这个库,看看是不是能解决我们的问题,于是我们开始吧

读fastclick源码

尼玛使用太简单了,直接一句:

FastClick.attach(document.body);

于是所有的click响应速度直接提升,刚刚的!什么input获取焦点的问题也解决了!!!尼玛如果真的可以的话,原来改页面的同事肯定会啃了我

一步步来,我们跟进去,入口就是attach方法:

FastClick.attach = function(layer) {
'use strict';
return new FastClick(layer);
};

这个兄弟不过实例化了下代码,所以我们还要看我们的构造函数:

function FastClick(layer) {
'use strict';
var oldOnClick, self = this;
 this.trackingClick = false;
 this.trackingClickStart = 0;
 this.targetElement = null;
 this.touchStartX = 0;
 this.touchStartY = 0;
 this.lastTouchIdentifier = 0;
 this.touchBoundary = 10;
 this.layer = layer;
 if (!layer || !layer.nodeType) {
 throw new TypeError('Layer must be a document node');
 }
 this.onClick = function() { return FastClick.prototype.onClick.apply(self, arguments); };
 this.onMouse = function() { return FastClick.prototype.onMouse.apply(self, arguments); };
 this.onTouchStart = function() { return FastClick.prototype.onTouchStart.apply(self, arguments); };
 this.onTouchMove = function() { return FastClick.prototype.onTouchMove.apply(self, arguments); };
 this.onTouchEnd = function() { return FastClick.prototype.onTouchEnd.apply(self, arguments); };
 this.onTouchCancel = function() { return FastClick.prototype.onTouchCancel.apply(self, arguments); };
 if (FastClick.notNeeded(layer)) {
 return;
 }
 if (this.deviceIsAndroid) {
 layer.addEventListener('mouseover', this.onMouse, true);
 layer.addEventListener('mousedown', this.onMouse, true);
 layer.addEventListener('mouseup', this.onMouse, true);
 }
 layer.addEventListener('click', this.onClick, true);
 layer.addEventListener('touchstart', this.onTouchStart, false);
 layer.addEventListener('touchmove', this.onTouchMove, false);
 layer.addEventListener('touchend', this.onTouchEnd, false);
 layer.addEventListener('touchcancel', this.onTouchCancel, false);
 
 if (!Event.prototype.stopImmediatePropagation) {
 layer.removeEventListener = function(type, callback, capture) {
 var rmv = Node.prototype.removeEventListener;
 if (type === 'click') {
 rmv.call(layer, type, callback.hijacked || callback, capture);
 } else {
 rmv.call(layer, type, callback, capture);
 }
 };
 
 layer.addEventListener = function(type, callback, capture) {
 var adv = Node.prototype.addEventListener;
 if (type === 'click') {
 adv.call(layer, type, callback.hijacked || (callback.hijacked = function(event) {
 if (!event.propagationStopped) {
 callback(event);
 }
 }), capture);
 } else {
 adv.call(layer, type, callback, capture);
 }
 };
 }
 if (typeof layer.onclick === 'function') {
 oldOnClick = layer.onclick;
 layer.addEventListener('click', function(event) {
 oldOnClick(event);
 }, false);
 layer.onclick = null;
}
}

看看这段代码,上面很多属性干了什么事情我也不知道......于是忽略了

if (!layer || !layer.nodeType) {
throw new TypeError('Layer must be a document node');
}

其中这里要注意,我们必须传入一个节点给构造函数,否则会出问题

然后这个家伙将一些基本的鼠标事件注册在自己的属性方法上了,具体是干神马的我们后面再说

在后面点有个notNeeded方法:

 FastClick.notNeeded = function(layer) {
 'use strict';
 var metaViewport;
 if (typeof window.ontouchstart === 'undefined') {
 return true;
 }
 if ((/Chrome/[0-9]+/).test(navigator.userAgent)) {
 if (FastClick.prototype.deviceIsAndroid) {
 metaViewport = document.querySelector('meta[name=viewport]');
 if (metaViewport && metaViewport.content.indexOf('user-scalable=no') !== -1) {
 return true;
 }
 } else {
 return true;
 }
 }
 if (layer.style.msTouchAction === 'none') {
 return true;
 }
 return false;
 };

这个方法用于判断是否需要用到fastclick,注释的意思不太明白,我们看看代码吧

首先一句:

if (typeof window.ontouchstart === 'undefined') {
 return true;
}

如果不支持touchstart事件的话,返回true
PS:现在的只管感受就是fastclick应该也是以touch事件模拟的,但是其没有点透问题

后面还判断了android的一些问题,我这里就不关注了,意思应该就是支持touch才能支持吧,于是回到主干代码

主干代码中,我们看到,如果浏览器不支持touch事件或者其它问题就直接跳出了

然后里面有个deviceIsAndroid的属性,我们跟去看看(其实不用看也知道是判断是否是android设备)

FastClick.prototype.deviceIsAndroid = navigator.userAgent.indexOf('Android') > 0;

绑定事件

好了,这家伙开始绑定注册事件了,至此还未看出异样

 if (this.deviceIsAndroid) {
 layer.addEventListener('mouseover', this.onMouse, true);
 layer.addEventListener('mousedown', this.onMouse, true);
 layer.addEventListener('mouseup', this.onMouse, true);
 }
 layer.addEventListener('click', this.onClick, true);
 layer.addEventListener('touchstart', this.onTouchStart, false);
 layer.addEventListener('touchmove', this.onTouchMove, false);
 layer.addEventListener('touchend', this.onTouchEnd, false);
 layer.addEventListener('touchcancel', this.onTouchCancel, false);

具体的事件函数在前面被重写了,我们暂时不管他,继续往后面看先(话说,这家伙绑定的事件够多的)

stopImmediatePropagation

完了多了一个属性:

阻止当前事件的冒泡行为并且阻止当前事件所在元素上的所有相同类型事件的事件处理函数的继续执行.

如果某个元素有多个相同类型事件的事件监听函数,则当该类型的事件触发时,多个事件监听函数将按照顺序依次执行.如果某个监听函数执行了 event.stopImmediatePropagation()方法,则除了该事件的冒泡行为被阻止之外(event.stopPropagation方法的作用),该元素绑定的其余相同类型事件的监听函数的执行也将被阻止.

 <html>
 <head>
  <style>
  p { height: 30px; width: 150px; background-color: #ccf; }
  p {height: 30px; width: 150px; background-color: #cfc; }
  </style>
 </head>
 <body>
  <p>
  <p>paragraph</p>
  </p>
  <script>
  document.querySelector("p").addEventListener("click", function(event)
  {
   alert("我是p元素上被绑定的第一个监听函数");
  }, false);
  document.querySelector("p").addEventListener("click", function(event)
  {
   alert("我是p元素上被绑定的第二个监听函数");
   event.stopImmediatePropagation();
   //执行stopImmediatePropagation方法,阻止click事件冒泡,并且阻止p元素上绑定的其他click事件的事件监听函数的执行.
  }, false);
  document.querySelector("p").addEventListener("click", function(event)
  {
   alert("我是p元素上被绑定的第三个监听函数");
   //该监听函数排在上个函数后面,该函数不会被执行.
  }, false);
  document.querySelector("p").addEventListener("click", function(event)
  {
   alert("我是p元素,我是p元素的上层元素");
   //p元素的click事件没有向上冒泡,该函数不会被执行.
  }, false);
  </script>
 </body>
 </html>
 if (!Event.prototype.stopImmediatePropagation) {
 layer.removeEventListener = function(type, callback, capture) {
 var rmv = Node.prototype.removeEventListener;
 if (type === 'click') {
 rmv.call(layer, type, callback.hijacked || callback, capture);
 } else {
 rmv.call(layer, type, callback, capture);
 }
 };
 
 layer.addEventListener = function(type, callback, capture) {
 var adv = Node.prototype.addEventListener;
 if (type === 'click') {
 adv.call(layer, type, callback.hijacked || (callback.hijacked = function(event) {
 if (!event.propagationStopped) {
 callback(event);
 }
 }), capture);
 } else {
 adv.call(layer, type, callback, capture);
 }
 };
 }

然后这家伙重新定义了下注册与注销事件的方法,

我们先看注册事件,其中用到了Node的addEventListener,这个Node是个什么呢?

由此观之,Node是一个系统属性,代表我们的节点吧,所以这里重写了注销的事件

这里,我们发现,其实他只对click进行了特殊处理

adv.call(layer, type, callback.hijacked || (callback.hijacked = function(event) {
if (!event.propagationStopped) {
 callback(event);
}
}), capture);

其中有个hijacked劫持是干神马的就暂时不知道了,估计是在中间是否改写的意思吧
然后这里重写写了下,hijacked估计是一个方法,就是为了阻止在一个dom上注册多次事件多次执行的情况而存在的吧

注销和注册差不多我们就不管了,到此我们其实重写了我们传入dom的注册注销事件了,好像很厉害的样子,意思以后这个dom调用click事件用的是我们的,当然这只是我暂时的判断,具体还要往下读,而且我觉得现在的判断不靠谱,于是我们继续吧

我们注销事件时候可以用addEventListener 或者 dom.onclick=function(){},所以这里有了下面的代码:

if (typeof layer.onclick === 'function') {
 oldOnClick = layer.onclick;
 layer.addEventListener('click', function(event) {
 oldOnClick(event);
 }, false);
 layer.onclick = null;
}

此处,他的主干流程居然就完了,意思是他所有的逻辑就在这里了,不论入口还是出口应该就是事件注册了,于是我们写个代码来看看

测试入口

 <input type="button" value="addevent">
 <input type="button" value="addevent1">
 $('#addEvent').click(function () {
 var dom = $('#addEvent1')[0]
 dom.addEventListener('click', function () {
  alert('')
  var s = '';
 })
 });

我们来这个断点看看我们点击后干了什么,我们现在点击按钮1会为按钮2注册事件:

但是很遗憾,我们在电脑上不能测试,所以增加了我们读代码的困难,在手机上测试后,发现按钮2响应很快,但是这里有点看不出问题

最后alert了一个!Event.prototype.stopImmediatePropagation发现手机和电脑都是false,所以我们上面搞的东西暂时无用

 FastClick.prototype.onClick = function (event) {
 'use strict';
 var permitted;
 alert('终于尼玛进来了');
 if (this.trackingClick) {
  this.targetElement = null;
  this.trackingClick = false;
  return true;
 }
 if (event.target.type === 'submit' && event.detail === 0) {
  return true;
 }
 permitted = this.onMouse(event);
 if (!permitted) {
  this.targetElement = null;
 }
 return permitted;
 };

然后我们终于进来了,现在我们需要知道什么是trackingClick 了

/**
* Whether a click is currently being tracked.
* @type Boolean
*/
this.trackingClick = false;

我们最初这个属性是false,但是到这里就设置为true了,就直接退出了,说明绑定事件终止,算了这个我们暂时不关注,我们干点其它的,

因为,我觉得重点还是应该在touch事件上

PS:到这里,我们发现这个库应该不只是将click加快,而是所有的响应都加快了

我在各个事件部分log出来东西,发现有click的地方都只执行了touchstart与touchend,于是至此,我觉得我的观点成立
他使用touch事件模拟量click,于是我们就只跟进这一块就好:

 FastClick.prototype.onTouchStart = function (event) {
 'use strict';
 var targetElement, touch, selection;
 log('touchstart');
 if (event.targetTouches.length > 1) {
  return true;
 }
 targetElement = this.getTargetElementFromEventTarget(event.target);
 touch = event.targetTouches[0];
 if (this.deviceIsIOS) {
  selection = window.getSelection();
  if (selection.rangeCount && !selection.isCollapsed) {
  return true;
  }
  if (!this.deviceIsIOS4) {
  if (touch.identifier === this.lastTouchIdentifier) {
   event.preventDefault();
   return false;
  }
  this.lastTouchIdentifier = touch.identifier;
  this.updateScrollParent(targetElement);
  }
 }
 this.trackingClick = true;
 this.trackingClickStart = event.timeStamp;
 this.targetElement = targetElement;
 this.touchStartX = touch.pageX;
 this.touchStartY = touch.pageY;
 if ((event.timeStamp - this.lastClickTime) < 200) {
  event.preventDefault();
 }
 return true;
 };

其中用到了一个方法:

FastClick.prototype.getTargetElementFromEventTarget = function (eventTarget) {
 'use strict';
 if (eventTarget.nodeType === Node.TEXT_NODE) {
 return eventTarget.parentNode;
 }
 return eventTarget;
};

他是获取我们当前touchstart的元素

然后将鼠标的信息记录了下来,他记录鼠标信息主要在后面touchend时候根据x、y判断是否为click
是ios情况下还搞了一些事情,我这里跳过去了

然后这里记录了一些事情就跳出去了,没有特别的事情,现在我们进入我们的出口touchend

 FastClick.prototype.onTouchEnd = function (event) {
 'use strict';
 var forElement, trackingClickStart, targetTagName, scrollParent, touch, targetElement = this.targetElement;
 log('touchend');
 if (!this.trackingClick) {
  return true;
 }
 if ((event.timeStamp - this.lastClickTime) < 200) {
  this.cancelNextClick = true;
  return true;
 }
 this.lastClickTime = event.timeStamp;
 trackingClickStart = this.trackingClickStart;
 this.trackingClick = false;
 this.trackingClickStart = 0;
 if (this.deviceIsIOSWithBadTarget) {
  touch = event.changedTouches[0];
  targetElement = document.elementFromPoint(touch.pageX - window.pageXOffset, touch.pageY - window.pageYOffset) || targetElement;
  targetElement.fastClickScrollParent = this.targetElement.fastClickScrollParent;
 }
 targetTagName = targetElement.tagName.toLowerCase();
 if (targetTagName === 'label') {
  forElement = this.findControl(targetElement);
  if (forElement) {
  this.focus(targetElement);
  if (this.deviceIsAndroid) {
   return false;
  }
  targetElement = forElement;
  }
 } else if (this.needsFocus(targetElement)) {
  if ((event.timeStamp - trackingClickStart) > 100 || (this.deviceIsIOS && window.top !== window && targetTagName === 'input')) {
  this.targetElement = null;
  return false;
  }
  this.focus(targetElement);
  if (!this.deviceIsIOS4 || targetTagName !== 'select') {
  this.targetElement = null;
  event.preventDefault();
  }
  return false;
 }
 if (this.deviceIsIOS && !this.deviceIsIOS4) {
  scrollParent = targetElement.fastClickScrollParent;
  if (scrollParent && scrollParent.fastClickLastScrollTop !== scrollParent.scrollTop) {
  return true;
  }
 }
 if (!this.needsClick(targetElement)) {
  event.preventDefault();
  this.sendClick(targetElement, event);
 }
 return false;
 };

这个家伙洋洋洒洒干了许多事情

这里纠正一个错误,他onclick那些东西现在也执行了......可能是我屏幕有变化(滑动)导致

if ((event.timeStamp - this.lastClickTime) < 200) {
 this.cancelNextClick = true;
 return true;
}

这个代码很关键,我们首次点击会执行下面的逻辑,如果连续点击就直接完蛋,下面的逻辑丫的不执行了......
这个不执行了,那么这个劳什子又干了什么事情呢?
事实上下面就没逻辑了,意思是如果确实点击过快,两次点击只会执行一次,这个阀值为200ms,这个暂时看来是没有问题的

好了,我们继续往下走,于是我意识到又到了一个关键点
因为我们用tap事件不能使input获得焦点,但是fastclick却能获得焦点,这里也许是一个关键,我们来看看几个与获取焦点有关的函数

 FastClick.prototype.focus = function (targetElement) {
 'use strict';
 var length;
 if (this.deviceIsIOS && targetElement.setSelectionRange) {
  length = targetElement.value.length;
  targetElement.setSelectionRange(length, length);
 } else {
  targetElement.focus();
 }
 };

setSelectionRange是我们的关键,也许他是这样获取焦点的......具体我还要下来测试,留待下次处理吧
然后下面如果时间间隔过长,代码就不认为操作的是同一dom结构了

最后迎来了本次的关键:sendClick,无论是touchend还是onMouse都会汇聚到这里

 FastClick.prototype.sendClick = function (targetElement, event) {
 'use strict';
 var clickEvent, touch;
 // On some Android devices activeElement needs to be blurred otherwise the synthetic click will have no effect (#24)
 if (document.activeElement && document.activeElement !== targetElement) {
  document.activeElement.blur();
 }
 touch = event.changedTouches[0];
 // Synthesise a click event, with an extra attribute so it can be tracked
 clickEvent = document.createEvent('MouseEvents');
 clickEvent.initMouseEvent('click', true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);
 clickEvent.forwardedTouchEvent = true;
 targetElement.dispatchEvent(clickEvent);
 };

他创建了一个鼠标事件,然后dispatchEvent事件(这个与fireEvent类似)

 //document上绑定自定义事件ondataavailable
 document.addEventListener('ondataavailable', function (event) {
 alert(event.eventType);
 }, false);
 var obj = document.getElementById("obj");
 //obj元素上绑定click事件
 obj.addEventListener('click', function (event) {
 alert(event.eventType);
 }, false);
 //调用document对象的 createEvent 方法得到一个event的对象实例。
 var event = document.createEvent('HTMLEvents');
 // initEvent接受3个参数:
 // 事件类型,是否冒泡,是否阻止浏览器的默认行为
 event.initEvent("ondataavailable", true, true);
 event.eventType = 'message';
 //触发document上绑定的自定义事件ondataavailable
 document.dispatchEvent(event);
 var event1 = document.createEvent('HTMLEvents');
 event1.initEvent("click", true, true);
 event1.eventType = 'message';
 //触发obj元素上绑定click事件
 document.getElementById("test").onclick = function () {
 obj.dispatchEvent(event1);
 };

至此,我们就知道了,我们为dom先绑定了鼠标事件,然后touchend时候触发了,而至于为什么本身注册的click未触发就要回到上面代码了

解决“点透”(成果)

有了这个思路,我们来试试我们抽象出来的代码:

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
 <title></title>
 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
 <style>
  #list { display: block; position: absolute; top: 100px; left: 10px; width: 200px; height: 100px; }
  p { display: block; border: 1px solid black; height: 300px; width: 100%; }
  #input { width: 80px; height: 200px; display: block; }
 </style>
 </head>
 <body>
 <p>
 </p>
 <p>
  <p>
  <input type="text" />
  </p>
 </p>
 <script type="text/javascript">
  var el = null;
  function getEvent(el, e, type) {
  e = e.changedTouches[0];
  var event = document.createEvent('MouseEvents');
  event.initMouseEvent(type, true, true, window, 1, e.screenX, e.screenY, e.clientX, e.clientY, false, false, false, false, 0, null);
  event.forwardedTouchEvent = true;
  return event;
  }
  list.addEventListener('touchstart', function (e) {
  var firstTouch = e.touches[0]
  el = firstTouch.target;
  t1 = e.timeStamp;
  })
  list.addEventListener('touchend', function (e) {
  e.preventDefault();
  var event = getEvent(el, e, 'click');
  el.dispatchEvent(event);
  })
  var list = document.getElementById('list');
  list.addEventListener('click', function (e) {
  list.style.display = 'none';
  setTimeout(function () {
   list.style.display = '';
  }, 1000);
  })
 </script>
 </body>
 </html>

这样的话,便不会点透了,这是因为zepto touch事件全部绑定值document,所以 e.preventDefault();无用
结果我们这里是直接在dom上,e.preventDefault();
便起了作用不会触发浏览器默认事件,所以也不存在点透问题了,至此点透事件告一段落......

帮助理解的图

代码在公司写的,回家后不知道图上哪里了,各位将就看吧

为什么zepto会点透/fastclick如何解决点透

我最开始就给老大说zepto处理tap事件不够好,搞了很多事情出来

因为他事件是绑定到document上,先touchstart然后touchend,根据touchstart的event参数判断该dom是否注册了tap事件,有就触发

于是问题来了,zepto的touchend这里有个event参数,我们event.preventDefault(),这里本来都是最上层了,这就代码压根没什么用

但是fastclick处理办法不可谓不巧妙,这个库直接在touchend的时候就触发了dom上的click事件而替换了本来的触发时间

意思是原来要350-400ms执行的代码突然就移到了50-100ms,然后这里虽然使用了touch事件但是touch事件是绑定到了具体dom而不是document上

所以e.preventDefault是有效的,我们可以阻止冒泡,也可以阻止浏览器默认事件,这个才是fastclick的精华部分,不可谓不高啊!!!

整个fastclick代码读来醍醐灌顶,今天收获很大,在此记录

后记

上面的说法有点问题,这修正一下:

首先,我们回到原来的zepto方案,看看他有什么问题:

因为js标准本不支持tap事件,所以zepto tap是touchstart与touchend模拟而出 zepto在初始化时便给document绑定touch事件,在我们点击时根据event参数获得当前元素,并会保存点下和离开时候的鼠标位置 根据当前元素鼠标移动范围判断是否为类点击事件,如果是便触发已经注册好的tap事件

然后fastclick处理比较与zepto基本一致,但是又有所不同

fastclick是将事件绑定到你传的元素(一般是document.body)

② 在touchstart和touchend后(会手动获取当前点击el),如果是类click事件便手动触发了dom元素的click事件

所以click事件在touchend便被触发,整个响应速度就起来了,触发实际与zepto tap一样

好了,为什么基本相同的代码,zepto会点透而fastclick不会呢?

原因是zepto的代码里面有个settimeout,而就算在这个代码里面执行e.preventDefault()也不会有用

这就是根本区别,因为settimeout会将优先级较低

有了定期器,当代码执行到setTimeout的时候, 就会把这个代码放到JS的引擎的最后面

而我们代码会马上检测到e.preventDefault,一旦加入settimeout,e.preventDefault便不会生效,这是zepto点透的根本原因

结语

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

在Nodejs下使用gm裁剪在合成图片

使用js如何调用json

使用Puppeteer图像识别技术如何实现百度指数爬虫

热心网友 时间:2022-04-22 20:25

FastClick 是 FT Labs 专门为解决移动端浏览器 300 毫秒点击延迟问题所开发的一个轻量级的库。简而言之,FastClick 在检测到 touchend 事件的时候,会通过 DOM 自定义事件立即触发一个模拟click 事件的click事件(自定义事件),并把浏览器在 300 毫秒之后真正触发的 click 事件阻止掉。
FastClick 非常实际地解决 300 毫秒点击延迟的问题。唯一的缺点可能也就是该脚本的文件尺寸 (尽管它不大)。如果你非常在意这点文件大小,可以尝试一下 Filament Group 的 Tappy!,或者 tap.js。两者都相当轻量,能够通过监听 tap 而非 click 事件来绕过 300 毫秒延迟。
当然,zepto库函数中,也有一个touch模块,此模块也包含tap事件,可以通过绑定tap来取代click事件。
但是zepto的tap事件会有点透问题。如何解决,请看下篇分解。
接下来,我们来详细了解一个问题:FastClick解决延迟点击的源码解析。
FastClick解决延迟点击的源码解析。
首先,我们来看FastClick的使用。
window.addEventListener( "load", function() {
FastClick.attach( document.body );
}, false );

这样就解决了 300 毫秒点击延迟的问题。
FastClick的源码:
FastClick.attach = function(layer) {
‘use strict‘;
return new FastClick(layer);
};

在FastClick的构造函数中,会有下面这段代码:
this.onClick = function() { return FastClick.prototype.onClick.apply(self, arguments); };

this.onMouse = function() { return FastClick.prototype.onMouse.apply(self, arguments); };

this.onTouchStart = function() { return FastClick.prototype.onTouchStart.apply(self, arguments); };

this.onTouchEnd = function() { return FastClick.prototype.onTouchEnd.apply(self, arguments); };

this.onTouchCancel = function() { return FastClick.prototype.onTouchCancel.apply(self, arguments); };

if (FastClick.notNeeded(layer)) {
return;
}
if (this.deviceIsAndroid) {
layer.addEventListener(‘mouseover‘, this.onMouse, true);
layer.addEventListener(‘mousedown‘, this.onMouse, true);
layer.addEventListener(‘mouseup‘, this.onMouse, true);
}
layer.addEventListener(‘click‘, this.onClick, true);
layer.addEventListener(‘touchstart‘, this.onTouchStart, false);
layer.addEventListener(‘touchend‘, this.onTouchEnd, false);
layer.addEventListener(‘touchcancel‘, this.onTouchCancel, false);
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
艾芙洛洗发水为什么不在商场销售商 艾芙洛洗发水是英国的吗 毕业生刚刚签了三方协议,想毁,怎么办 适合夫妻干的生意有哪些 新生蜜蜂多久出巢试飞 新生蜜蜂什么时候进行首次试飞? 蜜蜂几月几日出生外貌和颜色? 当脚模一定要脚趾修长吗 脚长成这样,能当脚膜吗 固话遇忙记存呼叫业务有什么特点? 什么是固话遇忙记存呼叫业务? 心血管堵塞30%,请问有什么治疗? ●颈动脉狭窄介入治疗适应症和禁忌症是什么? 路由器怎么设置联网 溶栓适应症 本课中指出什么是决定经济会如何增长 双卡手机如何注册两个 反驳“我们可以不需要老师只用互联网就可以学习“的观点的英语作文 适合七夕发的句子 七夕被虐的句子搞笑 七夕调侃句子 七夕节幽默风趣句子有哪些? touchstart为什么会被穿透 《火影》策划花火做过哪些忍者? 海南一民宅突发火情,天干物燥的秋天,如何避免火灾的发生? 广州沙面岛发生火灾了?什么情况 企业怎么申请收费吗,微信企业号需要收费吗,微信企业号收费标准? 企业微信是否收费,企业可以申请吗? 被狗咬伤可以用肥皂清洗伤口吗 被狗咬后怎么办 狗咬了用香皂水洗管用吗 戴明质量管理原则共有几条 循证决策在质量管理体系中是如何体现出来的? 以下哪些是新版标准质量管理原则 柏翠面包机为什么做完需要很长时间缓冲,才能做别的? 支付宝用我滴身份证注册了还能注册吗 颈椎病要如何改善预防?平常如何保健护理? 乳胶漆奶咖色怎么刷出来颜色很难看 颈椎病的护理措施有哪些 什么是‘指标股’具体解释 乳胶漆咖啡色调成白色如何? 浅咖色乳胶漆墙面搭配 乳胶漆墙面装修了解 我要调浅咖啡色乳胶漆用什么颜色的色浆调? 什么叫指标股? 海尔电热水器 仪表盘 为什么每次保存文件时候都要输入扩展名 为什么解压文件成功之后 在当前文件夹里找不到文件 一定要把文件名在地址栏里输入才能打开 华硕蓝屏0x0000007b怎么恢复 你好。华硕的电脑x555s。重装系统win7后开机无限0x0000007b蓝屏代码 魅族mx6官方标配与4g加32g的区别是? 石榴树可以扦插吗?