English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
In letzter Zeit hat das tap-Event für mich so einige Probleme verursacht, einer davon ist, dass man, um das Punktieren zu lösen, die alten click-Ereignisse in tap umwandeln muss, was dazu führt, dass wir die IE-Nutzer abwerfen
Natürlich könnte man eine Kompatibilität erreichen, aber niemand möchte alte Code ändern, daher haben wir heute das Ding namens fastclick vorgestellt
Dies ist das vierte Mal, dass ich über das Punktieren des tap-Events schreibe. Wir haben uns immer sehr um die Lösung des Problems mit der 'Punktierung' der Maske gekümmert, daher schlug unser Chef heute ein Repository namens fastclick vor, das letztendlich unser Problem gelöst hat
Und click muss nicht mehr durch tap ersetzt werden, daher sagte unser Chef mir ernsthaft, lasst mich doch, ich habe ja bereits E-Mails verschickt......
Daher habe ich am Nachmittag angefangen, die Bibliothek fastclick zu betrachten, um zu sehen, ob sie unser Problem lösen kann, und dann haben wir angefangen
Lesen Sie den Quellcode von fastclick
Das ist einfach zu verwenden, einfach einen Satz:
FastClick.attach(document.body);
Dadurch wird die Geschwindigkeit der Click-Response direkt verbessert, genau das! Auch das Problem mit der Fokusverlagerung von Eingabefeldern ist gelöst!!! Wenn das wirklich geht, hätte der Kollege, der den alten Seite geändert hat, mich bestimmt zerpflückt
Schritt für Schritt, wir gehen hinein, der Einstieg ist die attach-Methode:
FastClick.attach = function(layer) { 'use strict'; return new FastClick(layer); };
Dieser Bruder hat nur Code instanziert, daher müssen wir noch unseren Konstruktor betrachten:
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;
}
}
Sehen wir uns dieses Stück Code an, viele Eigenschaften haben, was sie tun, weiß ich nicht...... also ignoriert.
if (!layer || !layer.nodeType) { throw new TypeError('Layer must be a document node'); }
Dabei müssen wir eine Node an den Konstruktor übergeben, andernfalls kann es zu Problemen kommen
Dann dieses kleine Ding registriert einige grundlegende Mausereignisse in seinen Eigenschaftsmethoden, was genau daran geschieht, werden wir später sehen.
Im Folgenden gibt es einen notNeeded-Methoden:
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) {
if (metaViewport && metaViewport.content.indexOf('user-scalable=no') !== -1) {
return true;
}
} else {
return true;
}
}
if (layer.style.msTouchAction === 'none') {
return true;
}
return false;
};
Diese Methode wird verwendet, um zu bestimmen, ob fastclick verwendet werden muss, der Kommentar ist nicht klar, lassen wir uns das Code anschauen.
Erste Zeile:
if (typeof window.ontouchstart === 'undefined') { return true; }
Wenn das Event touchstart nicht unterstützt wird, wird true zurückgegeben.
PS: Derzeitige Empfindung ist, dass fastclick auch durch Touch-Events simuliert wird, aber es gibt kein Klickdurchgangsproblem.
Danach wurde auch auf einige Probleme von Android geprüft, die ich hier nicht weiterverfolgen werde, der Sinn scheint zu sein, dass nur, wenn der Touch unterstützt wird, auch die Unterstützung besteht, also zurück zum Hauptcode.
Im Hauptcode sehen wir, dass der Browser, wenn er den Touch-Event oder andere Probleme nicht unterstützt, direkt abgebrochen wird.
Dann gibt es eine Eigenschaft deviceIsAndroid, wir schauen nach (eigentlich wissen wir schon, dass es sich um die Pr�fung eines Android-Ger�ts handelt)
FastClick.prototype.deviceIsAndroid = navigator.userAgent.indexOf('Android') > 0;
Ereignis binden
Bis jetzt gibt es keine Auff�lligkeiten, als dieser Kerl begann, Ereignisse zu binden und zu registrieren
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);
Die spezifischen Ereignisfunktionen wurden im vorigen Abschnitt �berladen, wir konzentrieren uns momentan nicht darauf, sondern schauen weiter nach vorne (im �brigen, dieser Kerl hat viele gebundene Ereignisse)
stopImmediatePropagation
Es wurde ein weiteres Attribut hinzugef�gt:
Verhindern Sie das Aufblasen des aktuellen Ereignisses und verhindern Sie, dass die Ereignisbehandlungsfunktionen der gleichen Ereignistypen auf dem aktuellen Ereigniselement fortgesetzt werden.
Wenn ein Element mehrere gleichartige Ereignis-Abh�ngigkeiten f�r die gleiche Ereignistypen hat, werden die mehrere Ereignis-Abh�ngigkeiten nacheinander aufgerufen, wenn ein solcher Ereignistyp ausgel�st wird. Wenn eine Ereignis-Abh�ngigkeit die Methode event.stopImmediatePropagation() aufruft, wird der Ausbruch des Ereignisses verhindert (d.h. die Wirkung des Methods event.stopPropagation), und auch die Ausf�hrung der anderen f�r denselben Ereignistyp gebundenen Ereignis-Abh�ngigkeiten dieses Elements wird verhindert.
<html>
<head>
<style>
p { Höhe: 30px; width: 150px; background-color: #ccf; }
div {height: 30px; width: 150px; background-color: #cfc; }
</style>
</head>
<body>
<div>
<p>paragraph</p>
</div>
<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("div").addEventListener("click", function(event)
{
alert("我是div元素,我是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);
}
};
}
然后这家伙重新定义了下注册与注销事件的方法,
Zunächst schauen wir uns die Ereignisregistrierung an, bei der addEventListener von Node verwendet wird, was ist Node?
Daraus zu schließen, ist Node eine Systemeigenschaft, die unseren Knoten repräsentiert, daher haben wir die Abmeldeereignisse überschrieben
Hier, wir entdecken, dass er nur den click besonders behandelt
adv.call(layer, type, callback.hijacked || (callback.hijacked = function(event) { if (!event.propagationStopped) { callback(event); } }), capture);
Darin gibt es einen hijacked, der noch nicht bekannt ist, was er macht, was wahrscheinlich bedeutet, dass er in der Mitte geändert wird oder nicht
Dann haben wir hier nachgeschrieben, hijacked ist wahrscheinlich eine Methode, die dazu dient, die mehrfache Registrierung von Ereignissen auf einem DOM zu verhindern, um doppelte Ausführung zu vermeiden
Abmeldung und Registrierung sind ähnlich, also kümmern wir uns darum nicht, bis hierher haben wir tatsächlich die Registrierungs- und Abmeldeereignisse des übergebenen dom überschrieben, was sehr mächtig aussieht, was bedeutet, dass der dom in Zukunft den click-Ereignis mit unserem verwendet, natürlich ist dies nur meine vorläufige Einschätzung, genauer muss weitergelesen werden, und ich denke, meine aktuelle Einschätzung ist nicht zuverlässig, also fangen wir weiter an
Wir können die Ereignisabmeldung mit addEventListener oder dom.onclick=function(){} durchführen, daher haben wir den folgenden Code:
if (typeof layer.onclick === 'function') { oldOnClick = layer.onclick; layer.addEventListener('click', function(event) { oldOnClick(event); }, false); layer.onclick = null; }
Hier, sein Hauptfluss ist tatsächlich beendet, was bedeutet, dass alle seine Logiken hier sind, egal ob Eingang oder Ausgang sollte es sich um die Ereignisregistrierung handeln, also schreiben wir einen Code, um zu sehen
Test-Eingang
<input type="button" value="addevent">
<input type="button" value="addevent1">
$('#addEvent').click(function () {
var dom = $('#addEvent1')[0]
dom.addEventListener('click', function () {
alert('')
var s = '';
)
});
Lassen Sie uns diesen Breakpoint sehen, was wir nach dem Klicken tun, wir klicken jetzt auf die Schaltfläche1wird für die Schaltflächen2Ereignisregistrierung:
Leider können wir dies nicht auf dem Computer testen, daher wird es schwieriger, den Code zu lesen, nach dem Testen auf dem Telefon haben wir festgestellt, dass die Schaltflächen2Die Reaktion ist schnell, aber hier ist es schwer, ein Problem zu erkennen
Letztendlich wurde ein alert('!Event.prototype.stopImmediatePropagation') aufgerufen, und sowohl auf dem Telefon als auch auf dem Computer war das Ergebnis false, daher sind die von uns erstellten Dinge vorläufig nutzlos
FastClick.prototype.onClick = function (event) {
'use strict';
var permitted;
alert('Endlich haben wir es geschafft');
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;
};
Dann sind wir endlich hier, jetzt müssen wir wissen, was trackingClick ist
/** * Ob derzeit ein Click verfolgt wird. * @type Boolean */ this.trackingClick = false;
Wir hatten diese Eigenschaft ursprünglich auf false gesetzt, aber bis hierhin haben wir sie auf true gesetzt und direkt abgebrochen, was bedeutet, dass die Ereignisbindung beendet wurde, also lassen wir das erst einmal sein, machen wir etwas anderes
weil ich denke, dass der Fokus immer noch auf dem touch-Event liegen sollte
PS: Bis hierhin haben wir festgestellt, dass diese Bibliothek nicht nur den Click beschleunigen sollte, sondern alle Antworten beschleunigen
Ich habe in den verschiedenen Ereignisabschnitten etwas geloggt und festgestellt, dass an den Stellen, an denen click auftritt, nur touchstart und touchend ausgeführt werden, daher denke ich, dass meine Ansicht zutrifft
Er simuliert den Click über das touch-Event, daher verfolgen wir nur dies:
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;
};
Dabei wird ein Verfahren verwendet:
FastClick.prototype.getTargetElementFromEventTarget = function (eventTarget) { 'use strict'; if (eventTarget.nodeType === Node.TEXT_NODE) { return eventTarget.parentNode; } return eventTarget; };
Es handelt sich um das Erhalten des Elements, auf dem der aktuelle touchstart erfolgt
Dann wurden die Mausinformationen protokolliert, er protokolliert die Mausinformationen hauptsächlich im touchend-Moment, um anhand von x und y zu bestimmen, ob es sich um einen Click handelt
Es wurden unter iOS-Bedingungen einige Dinge erledigt, die ich hier übersprungen habe
Dann werden hier einige Dinge protokolliert und es wird hinausgesprungen, ohne dass etwas Besonderes passiert, wir betreten nun unseren Ausgang 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;
};
Dieser Kerl hat viele Dinge erledigt
Hier eine Korrektur eines Fehlers, er führt jetzt auch onclick-Sachen aus...... möglicherweise hat sich mein Bildschirm geändert (gescrollt)
if ((event.timeStamp - this.lastClickTime) < 200) { this.cancelNextClick = true; return true; }
Dieser Code ist sehr wichtig, bei unserem ersten Klick wird die folgende Logik ausgeführt, bei wiederholten Klicks wird es direkt kaputt sein, die folgende Logik wird nicht mehr ausgeführt......
Das wird nicht mehr ausgeführt, dann was hat dieser Schrott sonst noch getan?
Tatsächlich gibt es nach unten keine Logik mehr, was bedeutet, dass wenn die Klicks wirklich zu schnell sind, die beiden Klicks nur einmal ausgeführt werden, dieser Schwellenwert ist200ms, das scheint vorläufig kein Problem zu sein
Na, wir gehen weiter, und ich habe mich bewusst geworden, dass wir wieder an einem Schlüsselpunkt angelangt sind
Da wir das tap-Ereignis nicht verwenden können, um das input-Feld zu fokussieren, aber fastclick kann, könnte das hier ein Schlüssel sein, sehen wir uns einige Funktionen an, die mit dem Erhalten des Fokus in Verbindung stehen
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 ist unser Schlüssel, vielleicht funktioniert es so, dass er den Fokus erhält...... Ich muss noch testen, das werde ich beim nächsten Mal erledigen
Wenn die Zeitverzögerung zu lang ist, denkt der Code nicht mehr, dass die Operation auf die gleiche DOM-Struktur erfolgt
Endlich haben wir den Schlüssel dieses Mal erreicht: sendClick, egal ob touchend oder onMouse, sie werden hier zusammenlaufen
FastClick.prototype.sendClick = function (targetElement, event) {
'use strict';
var clickEvent, touch;
// Auf einigen Android-Geräten muss das activeElement verblendet werden, sonst hat der synthetische Click keine Wirkung (#24)
if (document.activeElement && document.activeElement !== targetElement) {
document.activeElement.blur();
}
touch = event.changedTouches[0];
// Erstelle ein Click-Ereignis mit einem zusätzlichen Attribut, damit es verfolgt werden kann
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);
};
Er hat ein Mausereignis erstellt und das Ereignis dispatchEvent ausgelöst (das ist ähnlich wie fireEvent)
//Ein benutzerdefiniertes Ereignis ondataavailable wird auf dem document-Element gebunden
document.addEventListener('ondataavailable', function (event) {
alert(event.eventType);
}, false);
var obj = document.getElementById("obj");
//Ein Click-Ereignis wird auf dem obj-Element gebunden
obj.addEventListener('click', function (event) {
alert(event.eventType);
}, false);
//Einen Event-Objekt-Instanz erhalten, indem das createEvent-Verfahren des Dokument-Objekts aufgerufen wird.
var event = document.createEvent('HTMLEvents');
// initEvent akzeptiert3Parameter:
// Ereignistyp, ob bubbelnd, ob das Standardverhalten des Browsers verhindert wird
event.initEvent("ondataavailable", true, true);
event.eventType = 'message';
//Triggeren des auf dem Dokument gebundenen benutzerdefinierten Ereignisses ondataavailable
document.dispatchEvent(event);
var event1 = document.createEvent('HTMLEvents');
event1.initEvent("click", true, true);
event1.eventType = 'message';
//Triggeren des click-Ereignisses, das dem obj-Element gebunden ist
document.getElementById("test").onclick = function () {
obj.dispatchEvent(event1);
};
Bis dahin wissen wir, dass wir für das DOM zunächst Mausereignisse gebunden haben und dann bei touchend ausgelöst haben, und warum der selbst registrierte click nicht ausgelöst wurde, müssen wir zu dem obigen Code zurückkehren
Lösen des "Durchdringens" (Ergebnis)
Mit diesem Ansatz, probieren wir das von uns abstrahierte Code aus:
!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; }
div { display: block; border: 1px solid black; height: 300px; width: 100%; }
#input { width: 80px; height: 200px; display: block; }
</style>
</head>
<body>
<div>
</div>
<div>
<div>
<input type="text" />
</div>
</div>
<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>
Dadurch wird das Durchdrücken verhindert, weil alle Zepto-Touch-Events auf das Dokument gebunden sind, daher ist e.preventDefault(); nutzlos
Das Ergebnis ist, dass wir direkt auf dem DOM sind, e.preventDefault();
dient und löst die Standardereignisse des Browsers nicht aus, daher gibt es auch kein Durchdrückungsproblem, das Problem des Durchdrückens ist somit beendet......
Hilfreiche Abbildung
Der Code wurde im Büro geschrieben, zu Hause weiß ich nicht, wo das Bild ist, bitte schaut euch das an
Warum drückt Zepto durch?/Wie löst fastclick das Problem des Durchdrückens?
Ich habe dem Chef bereits gesagt, dass Zepto die Tap-Events nicht gut behandelt, das hat viele Probleme verursacht
Weil das Ereignis auf das Dokument gebunden ist, wird zuerst touchstart und dann touchend aufgerufen, und basierend auf dem event-Parameter von touchstart wird überprüft, ob der DOM einen Tap-Event registriert hat, und wenn ja, wird er ausgelöst
Dadurch entsteht ein Problem, Zepto hat hier im touchend einen event-Parameter, wir rufen event.preventDefault() auf, das ist hier bereits am obersten Level, dieser Code ist praktisch nutzlos
Die Lösung von fastclick ist jedoch nicht weniger geschickt, diese Bibliothek löst direkt beim touchend den Click-Event auf dem DOM aus und ersetzt so die ursprüngliche Auslösetime
Das bedeutet, dass ursprünglich350-400ms ausgeführter Code wurde plötzlich hierhin verschoben50-100ms, und obwohl hier Touch-Events verwendet werden, sind diese an einen bestimmten DOM gebunden und nicht an das Dokument
Daher ist e.preventDefault() gültig, wir können das Blasen verhindern und auch den Standardereignissen des Browsers verhindern, das ist das Herzstück von fastclick, das kann nicht hoch genug bewertet werden!!!
Der gesamte Code von fastclick ist sehr lehrreich, ich habe heute viel gelernt und notiere das hier
Nachwort
Diese Aussage ist etwas ungenau, das korrigiere ich hier:
Zunächst kehren wir zu dem ursprünglichen Zepto-Plan zurück und schauen uns an, was dabei falsch geht:
Weichthin unterstützt der js-Standard keine Tap-Events, daher wird der Zepto Tap durch die Simulation von touchstart und touchend erstellt. Zepto bindet bereits bei der Initialisierung Touch-Events an das Dokument, erhält bei einem Klick den aktuellen Element basierend auf dem event-Parameter und speichert die Position des Mausdrückens und des Loslassens. Anhand der Bewegung des Mauszeigers innerhalb des aktuellen Elements wird überprüft, ob es sich um einen Klick-Event handelt. Wenn ja, wird der bereits registrierte Tap-Event ausgelöst.
Dann behandelt FastClick ähnlich wie Zepto, aber es gibt auch Unterschiede
FastClick bindet die Ereignisse an das übergebene Element (normalerweise document.body)
② Nach touchstart und touchend (wird manuell das aktuelle klicken el erhalten), wenn es sich um ein click-Event handelt, wird das click-Event des DOM-Elements manuell ausgelöst
Daher wird der Click-Event in touchend ausgelöst, und die gesamte Reaktionsgeschwindigkeit steigt, der Auslöser ist ähnlich wie Zepto tap
Nun, warum funktioniert Zepto Through-Hole, während FastClick nicht funktioniert?
Der Grund ist, dass im Zepto-Code ein setTimeout vorhanden ist, und selbst wenn e.preventDefault() darin ausgeführt wird, ist es nutzlos
Das ist der grundlegende Unterschied, weil setTimeout eine niedrigere Priorität hat
Mit einem Timer wird der Code in die letzte Position des JS-Engines gestellt, wenn der Code auf setTimeout ausgeführt wird
Unser Code erkennt e.preventDefault sofort, und wenn setTimeout hinzugefügt wird, funktioniert e.preventDefault nicht mehr, das ist der grundlegende Grund für das Through-Hole von Zepto
Schlusswort
Obwohl ich viele Umwege gegangen bin, wurde das Problem schließlich gelöst
Erklärung: Der Inhalt dieses Artikels wurde aus dem Internet übernommen und gehört dem Urheberrechtsinhaber. Der Inhalt wurde von Internetnutzern freiwillig beigesteuert und hochgeladen. Diese Website besitzt keine Eigentumsrechte und hat den Inhalt nicht manuell bearbeitet. Sie übernimmt auch keine rechtlichen Verantwortlichkeiten. Wenn Sie urheberrechtlich beanstandete Inhalte finden, freuen wir uns über eine E-Mail an: notice#oldtoolbag.com (Bitte ersetzen Sie # durch @, wenn Sie eine E-Mail senden, um zu melden, und fügen Sie relevante Beweise bei. Sobald nachgewiesen, wird diese Website die beanstandeten urheberrechtlichen Inhalte sofort löschen.)