日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

周末读fastclick.js源码有感

發布時間:2024/1/1 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 周末读fastclick.js源码有感 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

看之前需要知道:

// 創建一個事件對象,就好像你綁定事件回調函數里獲得的那個事件對象一樣 var myEvent = document.createEvent('Event')// 初始化這個事件對象,為它提高需要的“特性” myEvent.initEvent('myEventName', true, true)// 按照常見的方式綁定對該事件的監聽,這里的 element 可以是任何一個元素,你懂的 element.addEventListener('myEventName', function(evt) {// 這里,evt 就是你創建的事件對象了,不過它會更豐富一些——這些是瀏覽器為你做的 })// 然后這樣觸發它 element.dispatchEvent(myEvent)你必須要去閱讀 createEvent initEvent dispatchEvent 這些方法的文檔來完整認識它們(文檔可以去 MDN 找),上面介紹的只是基本用法。$.trigger() 所封裝的也就是它們(及其相關的兼容性處理等等)。不過這些方法已經有點“過時”了,特別像 initEvent 這樣的方法更是已經被(新的 DOM 標準)廢棄了。 以下是更“現代”的做法,不過老樣子:兼容性會是問題: var myEvent = new Event('myEventName')element.dispatchEvent(myEvent) 綁定回調是一樣的我就不重復了。另外“現代”的做法里觸發內建事件要用對應的接口,比如說: var event = new MouseEvent('click', {'view': window,'bubbles': true,'cancelable': true }); 其實除了具體方法的文檔外,更重要的是先理解整個事件對象模型體系,這是一個非常非常龐大的體 復制代碼;(function () {'use strict';//構造函數function FastClick(layer, options) {var oldOnClick;options = options || {};/*** Whether a click is currently being tracked.** @type boolean*/this.trackingClick = false;/*** Timestamp for when click tracking started.** @type number*/this.trackingClickStart = 0;/*** The element being tracked for a click.** @type EventTarget*/this.targetElement = null;/*** X-coordinate of touch start event.** @type number*/this.touchStartX = 0;/*** Y-coordinate of touch start event.** @type number*/this.touchStartY = 0;//主要hack iOS4下的一個怪異問題this.lastTouchIdentifier = 0;/*** 用于區分是click還是Touchmove,若出點移動超過該值則視為touchmove*/this.touchBoundary = options.touchBoundary || 10;/*** 綁定了FastClick的元素,常規是body*/this.layer = layer;/*** The minimum time between tap(touchstart and touchend) events** @type number*/this.tapDelay = options.tapDelay || 200;/*** The maximum time for a tap** @type number*/this.tapTimeout = options.tapTimeout || 700;//如果是屬于不需要處理的元素類型,則直接返回if (FastClick.notNeeded(layer)) {return;}//語法糖,兼容一些用不了 Function.prototype.bind 的舊安卓//所以后面不走 layer.addEventListener('click', this.onClick.bind(this), true);function bind(method, context) {return function() { return method.apply(context, arguments); };}var methods = ['onMouse', 'onClick', 'onTouchStart', 'onTouchMove', 'onTouchEnd', 'onTouchCancel'];var context = this;for (var i = 0, l = methods.length; i < l; i++) {context[methods[i]] = bind(context[methods[i]], context);}//安卓則做額外處理if (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 的瀏覽器(比如 Android 2)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') {//留意這里 callback.hijacked 中會判斷 event.propagationStopped 是否為真來確保(安卓的onMouse事件)只執行一次//在 onMouse 事件里會給 event.propagationStopped 賦值 trueadv.call(layer, type, callback.hijacked || (callback.hijacked = function(event) {if (!event.propagationStopped) {callback(event);}}), capture);} else {adv.call(layer, type, callback, capture);}};}// 如果layer直接在DOM上寫了 onclick 方法,那我們需要把它替換為 addEventListener 綁定形式if (typeof layer.onclick === 'function') {oldOnClick = layer.onclick;layer.addEventListener('click', function(event) {oldOnClick(event);}, false);layer.onclick = null;}}/*** Windows Phone 8.1 fakes user agent string to look like Android and iPhone.** @type boolean*/var deviceIsWindowsPhone = navigator.userAgent.indexOf("Windows Phone") >= 0;/*** Android requires exceptions.** @type boolean*/var deviceIsAndroid = navigator.userAgent.indexOf('Android') > 0 && !deviceIsWindowsPhone;/*** iOS requires exceptions.** @type boolean*/var deviceIsIOS = /iP(ad|hone|od)/.test(navigator.userAgent) && !deviceIsWindowsPhone;/*** iOS 4 requires an exception for select elements.** @type boolean*/var deviceIsIOS4 = deviceIsIOS && (/OS 4_\d(_\d)?/).test(navigator.userAgent);/*** iOS 6.0-7.* requires the target element to be manually derived** @type boolean*/var deviceIsIOSWithBadTarget = deviceIsIOS && (/OS [6-7]_\d/).test(navigator.userAgent);/*** BlackBerry requires exceptions.** @type boolean*/var deviceIsBlackBerry10 = navigator.userAgent.indexOf('BB10') > 0;//判斷元素是否要保留穿透功能FastClick.prototype.needsClick = function(target) {switch (target.nodeName.toLowerCase()) {// disabled的inputcase 'button':case 'select':case 'textarea':if (target.disabled) {return true;}break;case 'input':// file組件必須通過原生click事件點擊才有效if ((deviceIsIOS && target.type === 'file') || target.disabled) {return true;}break;case 'label':case 'iframe':case 'video':return true;}//元素帶了名為“bneedsclick”的class也返回truereturn (/\bneedsclick\b/).test(target.className);};//判斷給定元素是否需要通過合成click事件來模擬聚焦FastClick.prototype.needsFocus = function(target) {switch (target.nodeName.toLowerCase()) {case 'textarea':return true;case 'select':return !deviceIsAndroid; //iOS下的select得走穿透點擊才行case 'input':switch (target.type) {case 'button':case 'checkbox':case 'file':case 'image':case 'radio':case 'submit':return false;}return !target.disabled && !target.readOnly;default://帶有名為“bneedsfocus”的class則返回truereturn (/\bneedsfocus\b/).test(target.className);}};//合成一個click事件并在指定元素上觸發FastClick.prototype.sendClick = function(targetElement, event) {var clickEvent, touch;// 在一些安卓機器中,得讓頁面所存在的 activeElement(聚焦的元素,比如input)失焦,否則合成的click事件將無效if (document.activeElement && document.activeElement !== targetElement) {document.activeElement.blur();}touch = event.changedTouches[0];// 合成(Synthesise) 一個 click 事件// 通過一個額外屬性確保它能被追蹤(tracked)clickEvent = document.createEvent('MouseEvents');clickEvent.initMouseEvent(this.determineEventType(targetElement), true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);clickEvent.forwardedTouchEvent = true; // fastclick的內部變量,用來識別click事件是原生還是合成的targetElement.dispatchEvent(clickEvent); //立即觸發其click事件};FastClick.prototype.determineEventType = function(targetElement) {//安卓設備下 Select 無法通過合成的 click 事件被展開,得改為 mousedownif (deviceIsAndroid && targetElement.tagName.toLowerCase() === 'select') {return 'mousedown';}return 'click';};//設置元素聚焦事件FastClick.prototype.focus = function(targetElement) {var length;// 組件建議通過setSelectionRange(selectionStart, selectionEnd)來設定光標范圍(注意這樣還沒有聚焦// 要等到后面觸發 sendClick 事件才會聚焦)// 另外 iOS7 下有些input元素(比如 date datetime month) 的 selectionStart 和 selectionEnd 特性是沒有整型值的,// 導致會拋出一個關于 setSelectionRange 的模糊錯誤,它們需要改用 focus 事件觸發if (deviceIsIOS && targetElement.setSelectionRange && targetElement.type.indexOf('date') !== 0 && targetElement.type !== 'time' && targetElement.type !== 'month') {length = targetElement.value.length;targetElement.setSelectionRange(length, length);} else {//直接觸發其focus事件targetElement.focus();}};/*** 檢查target是否一個滾動容器里的子元素,如果是則給它加個標記*/FastClick.prototype.updateScrollParent = function(targetElement) {var scrollParent, parentElement;scrollParent = targetElement.fastClickScrollParent;// Attempt to discover whether the target element is contained within a scrollable layer. Re-check if the// target element was moved to another parent.if (!scrollParent || !scrollParent.contains(targetElement)) {parentElement = targetElement;do {if (parentElement.scrollHeight > parentElement.offsetHeight) {scrollParent = parentElement;targetElement.fastClickScrollParent = parentElement;break;}parentElement = parentElement.parentElement;} while (parentElement);}// 給滾動容器加個標志fastClickLastScrollTop,值為其當前垂直滾動偏移if (scrollParent) {scrollParent.fastClickLastScrollTop = scrollParent.scrollTop;}};/*** @param {EventTarget} targetElement* @returns {Element|EventTarget}*/FastClick.prototype.getTargetElementFromEventTarget = function(eventTarget) {// 一些較老的瀏覽器,target 可能會是一個文本節點,得返回其DOM節點if (eventTarget.nodeType === Node.TEXT_NODE) {return eventTarget.parentNode;}return eventTarget;};FastClick.prototype.onTouchStart = function(event) {var targetElement, touch, selection;// 多指觸控的手勢則忽略if (event.targetTouches.length > 1) {return true;}targetElement = this.getTargetElementFromEventTarget(event.target); //一些較老的瀏覽器,target 可能會是一個文本節點,得返回其DOM節點touch = event.targetTouches[0];if (deviceIsIOS) { //IOS處理// 若用戶已經選中了一些內容(比如選中了一段文本打算復制),則忽略selection = window.getSelection();if (selection.rangeCount && !selection.isCollapsed) {return true;}if (!deviceIsIOS4) { //是否IOS4//怪異特性處理——若click事件回調打開了一個alert/confirm,用戶下一次tap頁面的其它地方時,新的touchstart和touchend//事件會擁有同一個touch.identifier(新的 touch event 會跟上一次觸發alert點擊的 touch event 一樣),//為避免將新的event當作之前的event導致問題,這里需要禁用默認事件//另外chrome的開發工具啟用'Emulate touch events'后,iOS UA下的 identifier 會變成0,所以要做容錯避免調試過程也被禁用事件了if (touch.identifier && touch.identifier === this.lastTouchIdentifier) {event.preventDefault();return false;}this.lastTouchIdentifier = touch.identifier;// 如果target是一個滾動容器里的一個子元素(使用了 -webkit-overflow-scrolling: touch) ,而且滿足:// 1) 用戶非常快速地滾動外層滾動容器// 2) 用戶通過tap停止住了這個快速滾動// 這時候最后的'touchend'的event.target會變成用戶最終手指下的那個元素// 所以當快速滾動開始的時候,需要做檢查target是否滾動容器的子元素,如果是,做個標記// 在touchend時檢查這個標記的值(滾動容器的scrolltop)是否改變了,如果是則說明頁面在滾動中,需要取消fastclick處理this.updateScrollParent(targetElement);}}this.trackingClick = true; //做個標志表示開始追蹤click事件了this.trackingClickStart = event.timeStamp; //標記下touch事件開始的時間戳this.targetElement = targetElement;//標記touch起始點的頁面偏移值this.touchStartX = touch.pageX;this.touchStartY = touch.pageY;// this.lastClickTime 是在 touchend 里標記的事件時間戳// this.tapDelay 為常量 200 (ms)// 此舉用來避免 phantom 的雙擊(200ms內快速點了兩次)觸發 click// 反正200ms內的第二次點擊會禁止觸發點擊的默認事件if ((event.timeStamp - this.lastClickTime) < this.tapDelay) {event.preventDefault();}return true;};//判斷是否移動了//this.touchBoundary是常量,值為10//如果touch已經移動了10個偏移量單位,則應當作為移動事件處理而非click事件FastClick.prototype.touchHasMoved = function(event) {var touch = event.changedTouches[0], boundary = this.touchBoundary;if (Math.abs(touch.pageX - this.touchStartX) > boundary || Math.abs(touch.pageY - this.touchStartY) > boundary) {return true;}return false;};FastClick.prototype.onTouchMove = function(event) {//不是需要被追蹤click的事件則忽略if (!this.trackingClick) {return true;}// 如果target突然改變了,或者用戶其實是在移動手勢而非想要click// 則應該清掉this.trackingClick和this.targetElement,告訴后面的事件你們也不用處理了if (this.targetElement !== this.getTargetElementFromEventTarget(event.target) || this.touchHasMoved(event)) {this.trackingClick = false;this.targetElement = null;}return true;};//找到label標簽所映射的組件,方便讓用戶點label的時候直接激活該組件FastClick.prototype.findControl = function(labelElement) {// 有緩存則直接讀緩存著的if (labelElement.control !== undefined) {return labelElement.control;}// 獲取指向的組件if (labelElement.htmlFor) {return document.getElementById(labelElement.htmlFor);}// 沒有for屬性則激活頁面第一個組件(labellable 元素)return labelElement.querySelector('button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea');};FastClick.prototype.onTouchEnd = function(event) {var forElement, trackingClickStart, targetTagName, scrollParent, touch, targetElement = this.targetElement;if (!this.trackingClick) {return true;}// 避免 phantom 的雙擊(200ms內快速點了兩次)觸發 click// 我們在 ontouchstart 里已經做過一次判斷了(僅僅禁用默認事件),這里再做一次判斷if ((event.timeStamp - this.lastClickTime) < this.tapDelay) {this.cancelNextClick = true; //該屬性會在 onMouse 事件中被判斷,為true則徹底禁用事件和冒泡return true;}//this.tapTimeout是常量,值為700//識別是否為長按事件,如果是(大于700ms)則忽略if ((event.timeStamp - this.trackingClickStart) > this.tapTimeout) {return true;}// 得重置為false,避免input事件被意外取消// 例子見 https://github.com/ftlabs/fastclick/issues/156this.cancelNextClick = false;this.lastClickTime = event.timeStamp; //標記touchend時間,方便下一次的touchstart做雙擊校驗trackingClickStart = this.trackingClickStart;//重置 this.trackingClick 和 this.trackingClickStartthis.trackingClick = false;this.trackingClickStart = 0;// iOS 6.0-7.*版本下有個問題 —— 如果layer處于transition或scroll過程,event所提供的target是不正確的// 所以咱們得重找 targetElement(這里通過 document.elementFromPoint 接口來尋找)if (deviceIsIOSWithBadTarget) { //iOS 6.0-7.*版本touch = event.changedTouches[0]; //手指離開前的觸點// 有些情況下 elementFromPoint 里的參數是預期外/不可用的, 所以還得避免 targetElement 為 nulltargetElement = document.elementFromPoint(touch.pageX - window.pageXOffset, touch.pageY - window.pageYOffset) || targetElement;// target可能不正確需要重找,但fastClickScrollParent是不會變的targetElement.fastClickScrollParent = this.targetElement.fastClickScrollParent;}targetTagName = targetElement.tagName.toLowerCase();if (targetTagName === 'label') { //是label則激活其指向的組件forElement = this.findControl(targetElement);if (forElement) {this.focus(targetElement);//安卓直接返回(無需合成click事件觸發,因為點擊和激活元素不同,不存在點透)if (deviceIsAndroid) {return false;}targetElement = forElement;}} else if (this.needsFocus(targetElement)) { //非label則識別是否需要focus的元素//手勢停留在組件元素時長超過100ms,則置空this.targetElement并返回//(而不是通過調用this.focus來觸發其聚焦事件,走的原生的click/focus事件觸發流程)//這也是為何文章開頭提到的問題中,稍微久按一點(超過100ms)textarea是可以把光標定位在正確的地方的原因//另外iOS下有個意料之外的bug——如果被點擊的元素所在文檔是在iframe中的,手動調用其focus的話,//會發現你往其中輸入的text是看不到的(即使value做了更新),so這里也直接返回if ((event.timeStamp - trackingClickStart) > 100 || (deviceIsIOS && window.top !== window && targetTagName === 'input')) {this.targetElement = null;return false;}this.focus(targetElement);this.sendClick(targetElement, event); //立即觸發其click事件,而無須等待300ms//iOS4下的 select 元素不能禁用默認事件(要確保它能被穿透),否則不會打開select目錄//有時候 iOS6/7 下(VoiceOver開啟的情況下)也會如此if (!deviceIsIOS || targetTagName !== 'select') {this.targetElement = null;event.preventDefault();}return false;}if (deviceIsIOS && !deviceIsIOS4) {// 滾動容器的垂直滾動偏移改變了,說明是容器在做滾動而非點擊,則忽略scrollParent = targetElement.fastClickScrollParent;if (scrollParent && scrollParent.fastClickLastScrollTop !== scrollParent.scrollTop) {return true;}}// 查看元素是否無需處理的白名單內(比如加了名為“needsclick”的class)// 不是白名單的則照舊預防穿透處理,立即觸發合成的click事件if (!this.needsClick(targetElement)) {event.preventDefault();this.sendClick(targetElement, event);}return false;};FastClick.prototype.onTouchCancel = function() {this.trackingClick = false;this.targetElement = null;};//用于決定是否允許穿透事件(觸發layer的click默認事件)FastClick.prototype.onMouse = function(event) {// touch事件一直沒觸發if (!this.targetElement) {return true;}if (event.forwardedTouchEvent) { //觸發的click事件是合成的return true;}// 編程派生的事件所對應元素事件可以被允許// 確保其沒執行過 preventDefault 方法(event.cancelable 不為 true)即可if (!event.cancelable) {return true;}// 需要做預防穿透處理的元素,或者做了快速(200ms)雙擊的情況if (!this.needsClick(this.targetElement) || this.cancelNextClick) {//停止當前默認事件和冒泡if (event.stopImmediatePropagation) {event.stopImmediatePropagation();} else {// 不支持 stopImmediatePropagation 的設備(比如Android 2)做標記,// 確保該事件回調不會執行(見126行)event.propagationStopped = true;}// 取消事件和冒泡event.stopPropagation();event.preventDefault();return false;}//允許穿透return true;};//click事件常規都是touch事件衍生來的,也排在touch后面觸發。//對于那些我們在touch事件過程沒有禁用掉默認事件的event來說,我們還需要在click的捕獲階段進一步//做判斷決定是否要禁掉點擊事件(防穿透)FastClick.prototype.onClick = function(event) {var permitted;// 如果還有 trackingClick 存在,可能是某些UI事件阻塞了touchEnd 的執行if (this.trackingClick) {this.targetElement = null;this.trackingClick = false;return true;}// 依舊是對 iOS 怪異行為的處理 —— 如果用戶點擊了iOS模擬器里某個表單中的一個submit元素// 或者點擊了彈出來的鍵盤里的“Go”按鈕,會觸發一個“偽”click事件(target是一個submit-type的input元素)if (event.target.type === 'submit' && event.detail === 0) {return true;}permitted = this.onMouse(event);if (!permitted) { //如果點擊是被允許的,將this.targetElement置空可以確保onMouse事件里不會阻止默認事件this.targetElement = null;}//沒有多大意義return permitted;};//銷毀Fastclick所注冊的監聽事件。是給外部實例去調用的FastClick.prototype.destroy = function() {var layer = this.layer;if (deviceIsAndroid) {layer.removeEventListener('mouseover', this.onMouse, true);layer.removeEventListener('mousedown', this.onMouse, true);layer.removeEventListener('mouseup', this.onMouse, true);}layer.removeEventListener('click', this.onClick, true);layer.removeEventListener('touchstart', this.onTouchStart, false);layer.removeEventListener('touchmove', this.onTouchMove, false);layer.removeEventListener('touchend', this.onTouchEnd, false);layer.removeEventListener('touchcancel', this.onTouchCancel, false);};//是否沒必要使用到 Fastclick 的檢測FastClick.notNeeded = function(layer) {var metaViewport;var chromeVersion;var blackberryVersion;var firefoxVersion;// 不支持觸摸的設備if (typeof window.ontouchstart === 'undefined') {return true;}// 獲取Chrome版本號,若非Chrome則返回0chromeVersion = +(/Chrome\/([0-9]+)/.exec(navigator.userAgent) || [,0])[1];if (chromeVersion) {if (deviceIsAndroid) { //安卓metaViewport = document.querySelector('meta[name=viewport]');if (metaViewport) {// 安卓下,帶有 user-scalable="no" 的 meta 標簽的 chrome 是會自動禁用 300ms 延遲的,所以無需 Fastclickif (metaViewport.content.indexOf('user-scalable=no') !== -1) {return true;}// 安卓Chrome 32 及以上版本,若帶有 width=device-width 的 meta 標簽也是無需 FastClick 的if (chromeVersion > 31 && document.documentElement.scrollWidth <= window.outerWidth) {return true;}}// 其它的就肯定是桌面級的 Chrome 了,更不需要 FastClick 啦} else {return true;}}if (deviceIsBlackBerry10) { //黑莓,和上面安卓同理,就不寫注釋了blackberryVersion = navigator.userAgent.match(/Version\/([0-9]*)\.([0-9]*)/);if (blackberryVersion[1] >= 10 && blackberryVersion[2] >= 3) {metaViewport = document.querySelector('meta[name=viewport]');if (metaViewport) {if (metaViewport.content.indexOf('user-scalable=no') !== -1) {return true;}if (document.documentElement.scrollWidth <= window.outerWidth) {return true;}}}}// 帶有 -ms-touch-action: none / manipulation 特性的 IE10 會禁用雙擊放大,也沒有 300ms 時延if (layer.style.msTouchAction === 'none' || layer.style.touchAction === 'manipulation') {return true;}// Firefox檢測,同上firefoxVersion = +(/Firefox\/([0-9]+)/.exec(navigator.userAgent) || [,0])[1];if (firefoxVersion >= 27) {metaViewport = document.querySelector('meta[name=viewport]');if (metaViewport && (metaViewport.content.indexOf('user-scalable=no') !== -1 || document.documentElement.scrollWidth <= window.outerWidth)) {return true;}}// IE11 推薦使用沒有“-ms-”前綴的 touch-action 樣式特性名if (layer.style.touchAction === 'none' || layer.style.touchAction === 'manipulation') {return true;}return false;};FastClick.attach = function(layer, options) {return new FastClick(layer, options);};if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {// AMD. Register as an anonymous module.define(function() {return FastClick;});} else if (typeof module !== 'undefined' && module.exports) {module.exports = FastClick.attach;module.exports.FastClick = FastClick;} else {window.FastClick = FastClick;} }()); 復制代碼



JQuery 實現:

/*!* jQuery fastclick Plugin* http://www.zurb.com/playground/* Ported from Ryan Fioravanti's fast button article* http://code.google.com/mobile/articles/fast_buttons.html** Copyright 2011, ZURB* Released under the MIT License*/ (function ($) {$.event.special.fastclick = {add: function (handleObj) {var $this = $(this),startX,startY,coordinates = [];function onTouchStart(event) {event.stopPropagation();$(this).bind('touchend', onClick);$('body').bind('touchmove', onTouchMove);startX = event.originalEvent.touches[0].clientX;startY = event.originalEvent.touches[0].clientY;}function pop() {coordinates.splice(0, 2);}function preventGhostClick(x, y) {coordinates.push(x, y);window.setTimeout(pop, 2500);}function onClick(event) {event.stopPropagation();reset();handleObj.handler.apply(this, arguments);if (event.originalEvent.type == 'touchend') {preventGhostClick(startX, startY);}}function onTouchMove(event) {if (Math.abs(event.originalEvent.touches[0].clientX - startX) > 10 ||Math.abs(event.originalEvent.touches[0].clientY - startY) > 10) {reset();}}function reset() {$this.unbind('touchend');$('body').unbind('touchmove');}function clickBusterOnClick(event) {for (var i = 0; i < coordinates.length; i += 2) {var x = coordinates[i];var y = coordinates[i + 1];if (Math.abs(event.originalEvent.clientX - x) < 25 && Math.abs(event.originalEvent.clientY - y) < 25) {event.stopPropagation();event.preventDefault();}}}$this.bind('touchstart', onTouchStart);$this.bind('click', onClick);$(document).bind('click', clickBusterOnClick);}};}(jQuery));復制代碼



js原生創建模擬事件和自定義事件的方法

  • 模擬鼠標事件
    MDN上已經說得很清楚,盡管為了保持向后兼容MouseEvent.initMouseEvent()仍然可用,但是呢,我們應該使用MouseEvent().
    我們使用如下頁面做測試

    <!DOCTYPE html> <html> <head lang="zh-CN"><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1"/><title></title><style>.button {width: 200px;height: 200px;background-color: antiquewhite;margin: 20px;text-align: center;line-height: 200px;}</style> </head> <body><div class="button">Button</div><script>"use strict";var btn = document.querySelector('.button');btn.addEventListener('click', function (event) {console.log('OH~!You clicked me~!');}, false);var ev = new MouseEvent('click', {cancelable: true,bubble: true,view: window});btn.dispatchEvent(ev);</script> </body> </html>復制代碼

    打開一下這個頁面,并且在打開控制臺的情況下,你就可以看到控制臺打印了一句話,證明模擬成功了.


  • 總結

    以上是生活随笔為你收集整理的周末读fastclick.js源码有感的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。