preface
Recently, the company opened a new business line, and I was lucky to build a set of framework suitable for the new business from scratch with the big guys. As the saying goes, what suits you is the best 😎. In the CodeReview of the new project, I was mentioned by my brother whether fastClick was added to solve the 300ms delay problem on the mobile terminal. Here’s a look back at mobile latency.
introduce
Past life – The cause of birth
There Is a foreign article about the 300ms delay: What Exactly Is….. The 300ms Click Delay
Everything happens for a reason. When the web started on the desktop, who would have thought that mobile phones and other mobile devices would become so popular? I still remember that when I was in college, when I accessed the school website through my mobile phone, I controlled 🙃 through finger zooming. In my heart, I really felt ten thousand heads of mud galloping through. Later, in order to solve the problem of mobile terminal adaptation, I proposed the viewport solution. Based on accessibility (proxy required) interaction designers specifically provide gesture support for double click zoom for better user experience. Little do they know that this is the root of all the trouble.
This life – The fruit of death
Google has developer documentation: 300ms Tap Delay, Gone Away (proxy required)
The following is a partial quote from the original
For many years, mobile browsers applied a 300-350ms delay between touchend and click while they waited to see if this was going to be a double-tap or not, since double-tap was a gesture to zoom into text.
Roughly speaking, mobile browsers wait 300-350 ms between the TouchEnd and click events to determine whether the user will double-click to scale text.
Ever since the first release of Chrome for Android, this delay was removed if pinch-zoom was also disabled. However, pinch zoom is an important accessibility feature. As of Chrome 32 (back in 2014) this delay is gone for mobile-optimized sites, without removing pinch-zooming! Firefox and IE/Edge did the same shortly afterwards, and in March 2016 a similar fix landed in iOS 9.3.
There are a few important takeaways from this: First, Google has been talking about this delay since we launched Chrome mobile, as long as you turn zooming off, it doesn’t happen. Have to blow a wave of Google, is really a few streets away from Apple, fastClick source code is mostly used to solve various versions of iOS all kinds of weird bugs. To tell the truth, some source I am not very understand, but the za what also dare not say, what also dare not ask 😂. Second, Chrome 32 is optimized for mobile, so zooming doesn’t have to be a problem, and latency can also be solved. Firefox and IE/Edge followed suit, and finally, iOS 9.3 did the same (beta testing did fix it).
The solution
Here’s a hack to fix the lag without adding fastClick
Disable zoom
- Chrome on Android (all versions)
- IOS 9.3
<meta name="viewport" content="user-scalable=no" />
Copy the code
or
html {
touch-action: manipulation;
}
Copy the code
- IE on Windows Phone
html {
touch-action: manipulation; // IE11+
-ms-touch-action: manipulation; // IE10
}
Copy the code
Can’t help scaling
- Chrome 32+ on Android
- IOS 9.3
<meta name="viewport" content="width=device-width" />
Copy the code
After testing, if you do not add width=device-width, both Android and iOS versions will still have a delay problem.
WebView
All of the above is for mobile browsers, since it is mobile, of course, WebView has to say.
Android WebView
How to design an elegant and robust Android WebView?
The 300ms delay problem in Android WebView is the same as that in mobile browser.
iOS WebView
UIWebView
In apps that run in iOS 8 and later, use the WKWebView class instead of using UIWebView. Additionally, consider setting the WKPreferences property javaScriptEnabled to false if you render files that are not supposed to run JavaScript.
IOS WebView is a bit of a headache. Since iOS 8 was always a UIWebView, iOS 8 has a new WKWebView, so what’s the problem with the 300ms lag in iOS 9.3? With the help of the client iOS little sister, the final test result is that the UIWebView 300ms delay problem still exists even in the latest iOS version. 😂), but WKWebView fixed the problem in iOS 9.3. This means that WKWebView still has 300ms latency before iOS 9.3 (we worked hard to get it all sorted out 🙄).
FastClick principle analysis
This part may have a bit rotten avenue, one search on the net a big, say again also have no what meaning, I pick point individual feel interesting say 😁.
The principle of
First, let’s talk about how fastClick is implemented. MDN also supports both touch screen events and mouse events.
On the mobile side, when the user clicks the screen, touchStart, TouchMove (0 or more times), TouchEnd, Mousemove, MouseDown, mouseup, and Click will be triggered in sequence. Touchmove. The TouchMove event is triggered only when the finger moves on the screen. The Event. preventDefault, Mouse and Click events will not fire if either of the TouchStart, TouchMove or TouchEnd events is called.
FastClick calls Event.preventDefault in the TouchEnd phase and creates a MouseEvents with Document.createEvent, And then through the eventTarget. DispatchEvent trigger the corresponding target element binding on the click event.
You don’t knowJavaScript
(Maybe)
First of all, we need to clarify a problem. The 300ms delay is only available on mobile, not PC. A notNeeded function in fastClick is used to determine whether fastClick is needed. In the beginning, I read the code to express my dissatisfaction with the lack of a distinction between mobile and PC. But then a small piece of code changed my mind.
// Devices that don't support touch don't need FastClick
if (typeof window.ontouchstart === 'undefined') {
return true;
}
Copy the code
There is no touch event on PC, so window. onTouchStart returns undefined, and null if there is no binding event on mobile. As expected can only prove that I am still too young 🤣.
While reading the source code, I came across a bug in the mobile version of Safari using event delegates when click events are not bound to interactive elements (such as HTML divs) and there are no direct event listeners bound to them. The Click event is not emitted. See Click browser compatibility for details
The solution is as follows :(please forgive me for having the audacity to move directly to 😝)
- For its element or its ancestor element, add
cursor: pointer
Style to make the element interactive clickable - Add for elements that require interactive clicking
onclick="void(0)"
Property, but not the body element - Use clickable elements such as
<a>
, instead of non-interactive elements such as div - Do not use click’s event delegate.
Event. stopPropagation will only prevent the propagation of events of the same type (event. Type is the same). If I call Event. stopPropagation in TouchStart, it will only block subsequent TouchStart events on event flow, not TouchMove. The occurrence of mouseEvent such as Touchend.
Event. StopPropagation event. StopImmediatePropagation you really know the difference between a 🧐, event. StopPropagation stop capture and further spread of the current events in the bubbling phase. If there are multiple event listeners of the same type of event bound to the same element, when events of that type are fired, they are executed in the order in which they were added. If one of monitoring function performs the event. StopImmediatePropagation method, then the rest of the current element to monitor function will not be executed.
EventTarget. DispatchEvent will trigger a complete event flow, rather than just registered event trigger eventTarget itself.
In general, the process of reading source code is a process of self-cultivation, is the perfection of some deficiencies in the past, in fact, is to find themselves very dish 😂, the road ahead is dangerous and long, comrades still need to work hard 🤜.
insufficient
Personally feel that reading excellent source code is a very happy thing, because it can imperceptibly enhance your aesthetic ability. But at the same time we also want to have a critical eye, find out where there are shortcomings
In general, the notNeeded function in fastClick is pretty good, but the downside is that the introduction of fastClick is unnecessary and potentially problematic for those who use WKWebView on iOS 9.3 and above. As a Virgo, this is intolerable. But you can’t distinguish UIWebView from WKWebView simply by UA. However, if the page is in your App, you can carry the WebView information in the UA to decide whether to load or not
Delay detection code
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
<style></style>
</head>
<body>
<div>
<label for="userAgent">userAgent:</label>
<span id="userAgent"></span>
</div>
<div>
<label for="touchstart">touchstart:</label>
<span id="touchstart"></span>
</div>
<div>
<label for="touchend">touchend:</label>
<span id="touchend"></span>
</div>
<div>
<label for="click">click:</label>
<span id="click"></span>
</div>
<div>
<label for="diffClickTouchend">diff click - touchend:</label>
<span id="diffClickTouchend"></span>
</div>
<div>
<div id="test">test</div>
<div id="diff">diff</div>
</div>
<script>
var userAgent = document.getElementById('userAgent');
userAgent.innerText = window.navigator.userAgent;
var test = document.getElementById('test');
var diff = document.getElementById('diff');
var touchstart = document.getElementById('touchstart');
var touchend = document.getElementById('touchend');
var click = document.getElementById('click');
var diffClickTouchend = document.getElementById('diffClickTouchend');
test.addEventListener('touchstart'.function(e) {
touchstart.innerText = Date.now();
});
test.addEventListener('touchend'.function(e) {
touchend.innerText = Date.now();
});
test.addEventListener('click'.function(e) {
click.innerText = Date.now();
});
diff.addEventListener('click'.function() {
diffClickTouchend.innerText = click.innerText - touchend.innerText;
});
</script>
</body>
</html>
Copy the code
conclusion
Looking back at history, there is no denying that fastClick has made a great contribution to solving the 300ms latency problem on mobile, but is it still necessary to use 9102 today? Going back to the beginning, I said that what fits you is best, so if your business needs, You only need to adapt WKWebView for iOS 9.3 or above, so you are strongly advised not to use it, after all, it reduces the size of file request and introduces the probability of risk.
Finally, to quote the famous old soldier never dies, just fades in homage to fastClick.
Reference (References)
- What Exactly Is….. The 300ms Click Delay
- 300ms tap delay, gone away
- How to design an elegant and robust Android WebView?
- UIWebView
- Both touch screen events and mouse events are supported
- Click browser Compatibility
The text/lastSeries
The author is also in the nuggets oh, quickly follow him!
Sound/fluorspar
This article is authorized by chuangyu front-end author, copyright belongs to the author, chuangyu front-end production. Welcome to indicate the source of this article. Article link: juejin.cn/post/684490…
This article is the last time that Yingsheng is responsible for chuangyu’s front-end related accounts. Finally, we came to the end of a story together.
We all know that joy is the most difficult to get together.
Thank you for reading and for your continued support.
Good night.