Summary of H5 related problems at mobile terminal:
- Responsive layout
- iOS sliding is not smooth
- A white space appears in the iOS pull-up boundary drop-down
- The act of zooming in or out of a page piece
- click penetration and delay
- The pop-up of the soft keyboard causes the problem that the page is pushed up and stowed without falling back
- iPhone X bottom bar adaptation problem
- Save page as picture and QR code problems and Solutions
- WeChat official account H5 share problem
- Problems and solutions related to H5 calling SDK
- H5 commissioning related schemes and Strategies
wx01.jpg
1. iOS sliding is not smooth
performance
Sliding the page up and down will produce a jam. When your fingers leave the page, the page will stop moving immediately. The overall performance is that the sliding is not smooth and there is no sliding inertia.
Cause
Why doesn't iOS slide smoothly in webview? How is it defined? Originally, in iOS 5.0 and later versions, sliding is defined with two values auto and touch, and the default value is auto.
-webkit-overflow-scrolling: touch; /* When the finger is removed from the touch screen, it will keep scrolling for a period of time */ -webkit-overflow-scrolling: auto; /* When the finger is removed from the touch screen, the scrolling will stop immediately */
Solution
1. Add a rolling touch method on the rolling container
Set the - WebKit overflow scrolling value to touch
.wrapper { -webkit-overflow-scrolling: touch; }
Set scroll bar hide: container ::-webkit-scrollbar {display: none;}
position:fixed may be used; Fixed positioned elements that scroll with the page
2. Set overflow
Set the external overflow to hidden and the content element overflow to auto. When the internal element exceeds the body, it will roll, and the exceeding part of the body is hidden.
body { overflow-y: hidden; } .wrapper { overflow-y: auto; }
The combination of the two is better!
2, A white space appears in the iOS pull-up boundary drop-down
performance
Press and hold the screen drop-down with your finger, and a white area will appear at the top of the screen. Press and hold your finger on the screen and pull it up. There is an extra white area at the bottom.
Cause
In iOS, the touch move event will be triggered when the finger is pressed and dragged up and down the screen. The object triggered by this event is the entire webview container. The container will be dragged naturally, and the rest will be blank.
Solution
- Listen for events and prohibit sliding
There are three touch events at the mobile terminal, which are defined as
- touchstart: place your finger on a DOM element.
- touchmove: drag a DOM element with your finger.
- touchend: move your finger away from a DOM element.
The speed of the touchmove event can be defined, depending on hardware performance and other implementation details
The preventDefault method prevents all default behaviors on the same contact, such as scrolling.
Therefore, we find a solution. By listening to touchmove, we can slide where we need to slide and prohibit sliding where we don't need to slide.
It is worth noting that we want to filter out elements with rolling containers.
The implementation is as follows:
document.body.addEventListener('touchmove', function(e) { if(e._isScroller) return; // Block default events e.preventDefault(); }, { passive: false });
- Scroll to fill in the blank and decorate it with other functions
In many cases, we can change our thinking instead of solving this problem. According to the scenario, we can use drop-down as a functional operation.
For example, refresh the page or display copyright related information after drop-down
3, Page zoom in or out uncertainty behavior
performance
Double click or double finger open the page element, and the page will zoom in or out.
Cause
HTML itself will produce the behavior of zooming in or out. For example, on the PC browser, you can freely control the zooming in and out of the page. But on the mobile end, we don't need this behavior. Therefore, we need to prohibit this uncertain behavior to improve the user experience.
Principle and solution
There is a viewport attribute in the HTML meta tag standard, which is used to control the scaling of the page. It is generally used on the mobile terminal. The following figure is described in MDN
wx02.jpg
Conventional writing method of mobile terminal
<meta name="viewport" content="width=device-width, initial-scale=1.0">
Therefore, we can set maximum scale, minimum scale and user scale = no to avoid this problem
<meta name=viewport content="width=device-width, initial-scale=1.0, minimum-scale=1.0 maximum-scale=1.0, user-scalable=no">
4, Click click event delay and penetration
performance
Listen to the element click event, and the trigger time of clicking the element is delayed by about 300ms.
Click the mask. After the mask disappears, click the lower element to trigger.
Cause
Why does click delay occur?
safari in iOS, in order to realize the double-click zoom operation, if there is no second click after 300ms, click. That is, to judge whether the user behavior is generated by double clicking. However, in the App, whether you need to double-click to zoom or not, clicking will cause a 300ms delay.
Why does click penetration occur?
When double-layer elements are superimposed, the touch event is bound on the upper element and the click event is bound on the lower element. Because click occurs after touch, click the upper element, the element disappears, and the lower element will trigger the click event, resulting in the click penetration effect.
Principle and solution
Solution 1: replace click with touchstart
As described earlier, mobile devices support not only click, but also several touch events. So our basic idea now is to replace the click event with the touch event.
Replacing click with touchstart not only solves the delay problem of click events, but also solves the penetration problem. Because the penetration problem occurs when touch and click are mixed.
Use in native
el.addEventListener("touchstart", () => { console.log("ok"); }, false);
Use in vue
<button @touchstart="handleTouchstart()">click</button>
In the open source solution, both click event and touchstart event are provided. Such as the button component in vant
wx03.jpg
So, can I replace all click events with touchstart? Why does the open source framework give the click event?
We imagine a scenario that requires both clicking and sliding. What happens if you replace click with touchstart?
Event triggering sequence: touchstart, touchmove, touchend, click.
It's easy to imagine that when I need touchmove sliding, the touchstart click event is triggered first. Has there been a conflict?
Therefore, in the case of scrolling, it is recommended to use click processing.
The following processing is also done in the fastclick open source library. For touchstart and touchend, part of the source code is intercepted.
this.updateScrollParent(targetElement);
scrollParent = targetElement.fastClickScrollParent; if (scrollParent && scrollParent.fastClickLastScrollTop !== scrollParent.scrollTop) { return true; }
The main purpose is to ensure that the click event is not under the scrolling parent element when using touchstart to synthesize the click event.
Solution 2: use fastclick Library
Use after npm/yarn installation
import FastClick from 'fastclick'; FastClick.attach(document.body, options);
Similarly, after using the fastclick library, the click delay and penetration problems are eliminated
According to my practice, as long as the open source library is involved, we must understand the principle of its implementation. It mainly encapsulates the existing native event set into a highly compatible event set.
fastclick source code the core code is not long, less than 1000 lines. If you are interested, you can find out!
5, The soft keyboard pushes the page up and down without falling back
performance
In Android phones, when you click the input box, the keyboard pops up, pushing up the page, resulting in page style disorder.
When the focus is removed, the keyboard is retracted, and the keyboard area is blank without falling back.
Cause
We will have a fixed bottom in the app layout. In some Android versions, the input pop-up window will unzip the elements located by absolute and fixed. As a result, the visual area becomes smaller and the layout is disordered.
Principle and solution
The solution of jacking up the page with a soft keyboard is to forcibly restore the height before pop-up by monitoring the height change of the page.
// Record the original viewport height const originalHeight = document.body.clientHeight || document.documentElement.clientHeight; window.onresize = function(){ var resizeHeight = document.documentElement.clientHeight || document.body.clientHeight; if(resizeHeight < originalHeight ){ // Restore content area height // const container = document.getElementById("container") // For example, container style. height = originalHeight; } }
The keyboard cannot fall back. The problem occurs in iOS 12 + and wechat 6.7 4 +, which is a common Bug in wechat H5 development.
Compatibility principle, 1 Judge version type 2 Change the viewing area of scrolling
const isWechat = window.navigator.userAgent.match(/MicroMessenger\/([\d\.]+)/i); if (!isWechat) return; const wechatVersion = wechatInfo[1]; const version = (navigator.appVersion).match(/OS (\d+)_(\d+)_?(\d+)?/); // If the device type is iOS 12 + and wechat 6.7 4 +, restore to the original viewport if (+wechatVersion.replace(/\./g, '') >= 674 && +version[1] >= 12) { window.scrollTo(0, Math.max(document.body.clientHeight, document.documentElement.clientHeight)); }
window.scrollTo(x-coord, y-coord), where window Scrollto (0, clientheight) reverts to the original viewport
6, iPhone X series security zone adaptation problem
performance
In the areas on both sides or at the bottom of the bangs on the head, there are bangs blocking words, or blank areas on a black or white background.
Cause
IPhone X and its above series all use bangs and full screen gestures. The head, bottom and sides need special treatment. To adapt to the special circumstances of iPhone X.
Solution
Set up a safe area and fill the dangerous area. There is no operation and content display in the dangerous area.
Dangerous area refers to the irregular area of the head, the bottom bar area and the left and right trigger area.
wx04.jpg
The specific operations are as follows: set the viewport fit meta tag to cover to obtain all area fills. Judge whether the device belongs to iPhone X and add an adaptation layer to the bottom of the head
Viewport fit has three values:
- auto: this value does not affect the initial layout view port, and the entire web page is viewable.
- contain: the view port is scaled to fit the display of the largest embedded rectangle.
- cover: the view port is scaled to fill the device display. It is strongly recommended to use the safe - area inset variable to ensure that important content does not appear outside the display.
Set viewport fit to cover
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes, viewport-fit=cover">
Add adaptation layer
Use the safe area inset variable
/* Fit iPhone X top fill*/ @supports (top: env(safe-area-inset-top)){ body, .header{ padding-top: constant(safe-area-inset-top, 40px); padding-top: env(safe-area-inset-top, 40px); padding-top: var(safe-area-inset-top, 40px); } } /* Judge whether iPhoneX fills the padding bottom of the footer to the bottom */ @supports (bottom: env(safe-area-inset-bottom)){ body, .footer{ padding-bottom: constant(safe-area-inset-bottom, 20px); padding-bottom: env(safe-area-inset-bottom, 20px); padding-top: var(safe-area-inset-bottom, 20px); } }
Safe area inset top, safe area inset right, safe area inset bottom, safe - area inset left safe area inset - * consists of four environment variables that define the rectangle top, right, bottom and left in the viewport edge, so that the content can be safely placed without the risk of being cut off by non rectangular display. For rectangular viewports, such as a normal laptop monitor, the value is equal to zero. For non rectangular displays (such as round dial and iPhone x screen), all contents are visible within the rectangle formed by the four values set by the user agent.
Where env() is used as env (< custom ident >, < declaration value >?), The first parameter is a custom area and the second is an alternate value.
Where var() is used as var (< custom property name >, < declaration value >?), The function is to give a standby value when env() does not take effect.
constant () is the draft stage of CSS from 2017 to 2018. It is unknown whether it has been standardized. Whether this function is available in other iOS browser versions is unknown and added as a compatibility process.
7, Page generation becomes a problem of picture and QR code
performance
In work, there is a need to generate pictures or QR codes from the page. It may be our first thought that it is simpler to leave it to the back end to generate. But in this way, we need to pass all the page code to the back end, which consumes too much network performance.
Solution
Generate QR code
Generate QR code using QRCode
import QRCode from 'qrcode'; // Generate pictures using async const options = {}; const url = window.location.href; async url => { try { console.log(await QRCode.toDataURL(url, options)) } catch (err) { console.error(err); } }
Set await QRcode Todataurl (url, options) can be assigned to the image url
Generate picture
It mainly uses htmlToCanvas to generate canvas canvas
import html2canvas from 'html2canvas'; html2canvas(document.body).then(function(canvas) { document.body.appendChild(canvas); });
But it's not just here, because it's canvas. The picture generated by the mobile terminal is fuzzy.
We use a new canvas method to generate multiple times and put it into a double container to achieve a clearer effect. It is easy to download pictures and files through hyperlinks. It will be updated after a more complete implementation
const scaleSize = 2; const newCanvas = document.createElement("canvas"); const target = document.querySelector('div'); const width = parseInt(window.getComputedStyle(target).width); const height = parseInt(window.getComputedStyle(target).height); newCanvas.width = width * scaleSize; newCanvas.height = widthh * scaleSize; newCanvas.style.width = width + "px"; newCanvas.style.height =width + "px"; const context = newCanvas.getContext("2d"); context.scale(scaleSize, scaleSize); html2canvas(document.querySelector('.demo'), { canvas: newCanvas }).then(function(canvas) { // Simply set the download function through the hyperlink document.querySelector(".btn").setAttribute('href', canvas.toDataURL()); }
Set the scaleSize size as needed
Eight, WeChat official account sharing problem
performance
In the development of WeChat official account H5, the SDK is not effective when calling the share button inside the page.
Solution
Solution: add a layer of mask to share and guide.
Because clicking the share button inside the page cannot be called directly, and the share function needs to be operated by clicking more in the upper right corner.
Then users may not know the function sharing through the small label in the upper right corner. If you want to guide users to share, what should you do?
If the technology cannot be realized, start from the product.
wx05.jpg
If the technical implementation is complex or cannot be implemented directly. Don't force yourself into a corner. Learning to deal with products is also one of the necessary abilities of programmers.
9, H5 call SDK related solutions
Cause
Using H5 in Hybrid App is the most common. However, it must be strange and vague for those who have just come into contact. I don't know how H5 and Hybrid interact. How to support iOS and Android at the same time? Now let's talk about the key points of Hybrid technology, the communication between native and H5.
Solution
SDK team provides methods
1. Registration method bridge register
bridge.register('enterApp', function() { broadcast.emit('ENTER_APP') })
2. Callback method bridge call
export const getSDKVersion = () => bridge.call('BLT.getSDKVersion')
Event monitoring and triggering method
const broadcast = { on: function(name, fn, pluralable) { this._on(name, fn, pluralable, false) }, once: function(name, fn, pluralable) { this._on(name, fn, pluralable, true) }, _on: function(name, fn, pluralable, once) { let eventData = broadcast.data let fnObj = { fn: fn, once: once } if (pluralable && Object.prototype.hasOwnProperty.call(eventData, 'name')) { eventData[name].push(fnObj) } else { eventData[name] = [fnObj] } return this }, emit: function(name, data, thisArg) { let fn, fnList, i, len thisArg = thisArg || null fnList = broadcast.data[name] || [] for (i = 0, len = fnList.length; i < len; i++) { fn = fnList[i].fn fn.apply(thisArg, [data, name]) if (fnList[i].once) { fnList.splice(i, 1) i-- len-- } } return this }, data: {} } export default broadcast
Step on the pit
Before calling a method, you must judge whether the SDK provides the method. If Android provides the method, a pop-up window such as method call failure will appear on iOS. How to solve it?
Provide a way to judge whether Android and iOS are available. Judge according to equipment
export const hasNativeMethod = (name) => return bridge.hasNativeMethod('BYJ.' + name) } export const getSDKVersion = function() { if (hasNativeMethod('getSDKVersion')) { bridge.call('BYJ.getSDKVersion') } }
The same function requires iOS and Android with the same method name, which is better handled
10, H5 commissioning related scheme and strategy
performance
Debugging code is generally to view data and locate bugs. There are two scenarios, one is debugging during development and test, and the other is debugging in production environment.
Why is there debugging in the production environment? Sometimes this bug cannot be reproduced in the test environment, and the test environment is inconsistent with the production environment. At this time, urgent production debugging is required.
When developing on the PC side, we can directly drop out of the console and use the tools provided by the browser to operate devtools or view logs. But what do we do inside the App?
Principle and solution
- vconsole console plug-in
The method of use is also very simple
import Vconsole from 'vconsole' new Vconsole()
The above methods are for development and testing only. It is not allowed in the production environment, so it is necessary to judge the environment when using it.
import Vconsole from 'vconsole' if (process.env.NODE_ENV !== 'production') { new Vconsole() }
- Agent + spy debugger
The operation is a little troublesome, but I will write it in detail, which is roughly divided into four steps
1. Install plug-ins (Global installation)
sudo npm install spy-debugger -g
2. The mobile phone and the computer are placed under the same wifi, and the mobile phone is set with an agent
Set the HTTP proxy of the mobile phone. The proxy IP address is set to the IP address of the PC and the port is the startup port of spy debugger
Spy debugger default port: 9888 Android: settings - WLAN - long press to select the network - modify the network - Advanced - proxy settings - Manual IOS: settings - Wi Fi - select the network, click the exclamation point, HTTP proxy manually
3. The mobile phone opens the H5 page in the browser or app. 4. Open the desktop log website for debugging, and click the npm console listening address. View packet capture and H5 page structure