☞ Mobile end adaptation and PC end adaptation experience (a) (may be more complete
Problems with Web adaptation
1. The browser mate specifies the kernel
QQ browser meta element detection and identification kernel rules
Identified as the Chrome kernel
- Doctype for the standard
- Meta tag element
Example:
<! DOCTYPEhtml>
<html>
<head>
<! -- Select one of the following meta to correctly identify -->
<meta name="renderer" content="webkit" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="X-UA-Compatible" content="chrome=1" />
<title>chrome core</title>
</head>
<body>
meta webkit
</body>
</html>
Copy the code
Identifies as an IE kernel
- Doctype is non-standard
- Meta Element detection
Example:
<! DOCTYPEhtml PUBLIC "- / / / / W3C DTD XHTML 1.0 Transitional / / EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<! -- Select one of the following meta to correctly identify -->
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
<meta name="renderer" content="ie-comp" />
<meta name="renderer" content="ie-stand" />
<title>ie core</title>
</head>
<body>
meta ie
</body>
</html>
Copy the code
Reference: QQ browser document
2. 1px borders
Causes of occurrence:
According to the size of iPhone6, a 750px wide design drawing is actually the device pixel of iPhone6. The 1px measured in the design drawing is actually 1 device pixel. When we set the layout viewport equal to the ideal viewport equal to 375px, and since the DPR of iPhone6 is 2, When writing CSS, 1px corresponds to 2 device pixels, so it will look thicker.
The solution
1.border-image
Judge different device pixel ratio based on media query given different border-image:
.border_1px{
border-bottom: 1px solid # 000;
}
@media only screen and (-webkit-min-device-pixel-ratio:2) {.border_1px{
border-bottom: none;
border-width: 0 0 1px 0;
border-image: url(../img/1pxline.png) 0 0 2 0stretch; }}Copy the code
2. background-image
Similar to the border-image, prepare a qualified border background image and simulate it on the background.
.border_1px{
border-bottom: 1px solid # 000;
}
@media only screen and (-webkit-min-device-pixel-ratio:2{
.border_1px{
background: url(../img/1pxline.png) repeat-x left bottom;
background-size: 100% 1px; }}Copy the code
Both require separate images, and rounded corners are not easy to handle, but will work for most scenes.
3. Pseudo-class + transform
Determine the pixel ratio of different devices based on media query to scale the line:
.border_1px:before{
content: ' ';
position: absolute;
top: 0;
height: 1px;
width: 100%;
background-color: # 000;
transform-origin: 50% 0%;
}
@media only screen and (-webkit-min-device-pixel-ratio:2) {.border_1px:before{
transform: scaleY(0.5); }}@media only screen and (-webkit-min-device-pixel-ratio:3) {.border_1px:before{
transform: scaleY(0.33); }}Copy the code
This method can be used for various scenarios. If rounded corners are needed, just add border-radius to the pseudo-class.
4. Use SVG (plug-in helppostcss-write-svg
)
The above border-image and background-image can simulate 1px borders, but they are bitmaps and need to be imported externally.
With postCSs-write-svg we can create a 1px border for SVG directly using border-image and background-image:
@svg border_1px {
height: 2px;
@rect {
fill: var(--color, black);
width: 100%;
height: 50%; }}.example { border: 1px solid transparent; border-image: svg(border_1px param(--color #00b1ff)) 2 2 stretch; }
Copy the code
The compiled:
.example { border: 1px solid transparent; border-image: url("data:image/svg+xml; charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' height='2px'%3E%3Crect fill='%2300b1ff' width='100%25' height='50%25'/%3E%3C/svg%3E") 2 2 stretch; }
Copy the code
3. The adapter iPhoneX
We need to properly place the top and bottom within the security zone. In iOS11, two new CSS functions, env and constant, are used to set the distance between the security zone and the boundary.
There can be four constants inside a function:
safe-area-inset-left
: Distance between the security zone and the left boundarysafe-area-inset-right
: Distance between the security zone and the right boundarysafe-area-inset-top
: Distance between the security zone and the top boundarysafe-area-inset-bottom
: Distance between the security zone and the bottom boundary
Note: We must specify viweport-fit to use these two functions:
<meta name="viewport" content="width=device-width, viewport-fit=cover">
Copy the code
Constant works on iOS < 11.2, env works on iOS >= 11.2, which means we tend to set them both, limiting pages to safe zones:
body {
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
Copy the code
When using the bottom fixed navigation bar, we need to set the padding value for them:
{
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
Copy the code
Specific details
Aotu. IO/notes / 2017 /…
4. Landscape
Js recognition
window.addEventListener("resize".() = >{
if (window.orientation === 180 || window.orientation === 0) {
// Rotate the screen 180 degrees in normal direction
console.log('portrait');
};
if (window.orientation === 90 || window.orientation === -90) {// The screen rotates 90 degrees clockwise or 90 degrees counterclockwise
console.log('landscape'); }});Copy the code
The CSS to identify
@media screen and (orientation: portrait) {
/ * vertical screen... * /
}
@media screen and (orientation: landscape) {
/ * landscape... * /
}
Copy the code
5. Blurred pictures
1 Causes
Most of the images we use are bitmaps (PNG, JPG..) A bitmap is made up of individual pixels, each with a specific position and color value:
In theory, each pixel of the bitmap should be rendered using one physical pixel on the screen for optimal display.
On a screen with DPR > 1, a pixel of the bitmap may be rendered by multiple physical pixels. However, these physical pixels cannot be accurately assigned to the color of the corresponding bitmap pixel, and can only be approximated, so the same image will be blurred on a screen with DPR > 1:
2 Solution
In order to ensure image quality, we should render one image pixel with one screen pixel as much as possible, so we need to display images with different resolutions for different DPR screens.
For example, display a double graph (@2x) on a screen with DPR =2 and a triple graph (@3x) on a screen with DPR =3.
3 media query
Use media query to judge the pixel ratio of different devices to display pictures with different precision:
.avatar{
background-image: url(conardLi_1x.png);
}
@media only screen and (-webkit-min-device-pixel-ratio:2) {.avatar{
background-image: url(conardLi_2x.png); }}@media only screen and (-webkit-min-device-pixel-ratio:3) {.avatar{
background-image: url(conardLi_3x.png); }}Copy the code
Only for background images
4 image-set
Use the image – set:
.avatar {
background-image: -webkit-image-set( "conardLi_1x.png" 1x, "conardLi_2x.png" 2x );
}
Copy the code
Only for background images
5 srcset
Using the srcset attribute of the IMG tag, the browser automatically matches the best display image based on pixel density:
<img src="conardLi_1x.png"
srcset=" conardLi_2x.png 2x, conardLi_3x.png 3x">
Copy the code
6 JavaScript Splicing image URL
Use window.devicePixelRatio to get the devicePixelRatio, traverse all the images, and replace the image address:
const dpr = window.devicePixelRatio;
const images = document.querySelectorAll('img');
images.forEach((img) = >{
img.src.replace(".".` @${dpr}x.`);
})
Copy the code
7 using SVG
SVG stands for scalable vector graphics. Unlike bitmaps, which are pixel-based, SVG is a shape description of an image, so it is essentially a text file, small in size and undistorted no matter how many times it is magnified.
In addition to drawing SVG manually in code, we can also use SVG images as bitmaps:
<img src="conardLi.svg">
<img src="data:image/svg+xml; base64,[data]">
.avatar {
background: url(conardLi.svg);
}
Copy the code
Reference:
Mobile adaptation
Headlines mobile adaptation
H5 related
What is the h5
H5 technology is a set of mobile web front-end technologies
The H5 technology itself is the Web page for mobile. As the App itself has a webView container, in which Web front-end codes can be run, Hybrid App technology is derived from the combination of H5 and native App.
General principles of Hybrid App technology
Mobile responsive layout
Solution 1: REM + pxToRem
The principle of
- Monitor the width of the screen window, assigned by a proportional conversion to
html
thefont-size
. At this point, the root font size varies with the screen width. - will
px
Converted torem
There are two kinds of conventional programs. One is to usesass
/less
Custom function inpxToRem
Write,px
The use ofpxToRem
Function conversion torem
. The other way is to just write itpx
, the compilation process uses plug-ins to convert allrem
. suchdom
The size of the element in the screen will change with the screen width.
implementation
- Dynamically update the root font size
const MAX_FONT_SIZE = 420
// Define the maximum screen width
document.addEventListener('DOMContentLoaded'.() = > {
const html = document.querySelector('html')
let fontSize = window.innerWidth / 10
fontSize = fontSize > MAX_FONT_SIZE ? MAX_FONT_SIZE : fontSize
html.style.fontSize = fontSize + 'px'
})
Copy the code
px
转rem
pxToRem
Plan a
$rootFontSize: 375 / 10; // Define the function where px is converted to rem@function px2rem ($px) {
@return $px / $rootFontSize + rem;
}
.demo {
width: px2rem(100);
height: px2rem(100);
}
Copy the code
pxToRem
Scheme 2
Install the PostCSS-Pxtorem plugin in VuE-CLI3. Other platforms have similar ideas.
const autoprefixer = require('autoprefixer')
const pxtorem = require('postcss-pxtorem')
module.exports = {
// ...
css: {
sourceMap: true.loaderOptions: {
postcss: {
plugins: [
autoprefixer(),
pxtorem({
rootValue: 37.5.propList: [The '*']})]}}}}Copy the code
Continue to explore postCSS-PxtoREM plug-in source code, see how it is implemented.
function createPxReplace (rootValue, unitPrecision, minPixelValue) {
return function (m, $1) {
if(! $1) return m;
var pixels = parseFloat($1);
if (pixels < minPixelValue) return m;
var fixedVal = toFixed((pixels / rootValue), unitPrecision);
return (fixedVal === 0)?'0' : fixedVal + 'rem';
};
}
Copy the code
The transformation of PX into REM is mainly this function, of course, there are a lot of configurable parameters, the core principle is similar to our plan 1. The convenience is that you don’t have to add a function every time you write px, and the code is much cleaner.
Should all elements px be converted to REM? That’s not true, px should not be converted to REM in the border, which is another 1px problem, as discussed in the previous article. Avoid converting PX to REM, and capitalize px in the border to PX/ px/px
Solution 2: VH + VW
The principle of
vw
A unit of window width that varies with width.
implementation
Similarly, postCSS-pxtoREM is configured using the postCSs-pxto-viewPort plugin. Plug-ins work the same way
Other Solutions
plan | defects | |
---|---|---|
1 | The percentage | Height failure percentage |
2 | Media Enquiries +meta 中 viewport |
Different devices have different widths, and the scaling ratio cannot be completely determined |
3 | flex |
It still doesn’t solve the width overrun problem |
All of the above schemes have fatal defects and are not recommended for mobile terminal layout calculation.
Flex is best used with REM
Vue quickly configures mobile templates
reference
Open source library solutions
1. The vant component library
In the Vant component library, px is used as the measurement unit by default. If rem is needed, the plug-in is perfect for it.
For VW scenarios, Vant can also convert PX to VW through plug-ins, and there may be some pothole points for VW.
2. The ant – design – mobile component library
The Ant-Design-Mobile component library still uses px units
@hd: 1px; // Basic unit // font size // --@font-size-icontext: 10 * @hd;
@font-size-caption-sm: 12 * @hd;
@font-size-base: 14 * @hd;
@font-size-subhead: 15 * @hd;
@font-size-caption: 16 * @hd;
@font-size-heading: 17* @hd; // round corners // --@radius-xs: 2 * @hd;
@radius-sm: 3 * @hd;
@radius-md: 5 * @hd;
@radius-lg: 7 * @hd;
@radius-circle: 50%; // Frame size // --@border-width-sm: 1PX;
@border-width-md: 1PX;
@border-width-lg: 2 * @hd;
Copy the code
Summary of h5 problems
1. Ios doesn’t swipe smoothly
performance
Swiping up and down the page creates a stutter, and when your finger leaves the page, the page immediately stops moving. The overall performance is not smooth sliding, no sliding inertia.
The reasons causing
Why is iOS webView not sliding smoothly, and how is it defined?
In iOS 5.0 and later, there are two values for sliding: auto and touch. The default is auto.
-webkit-overflow-scrolling: touch; /* When the finger is removed from the touch screen, it keeps scrolling for a while */
-webkit-overflow-scrolling: auto; /* When the finger is removed from the touch screen, scrolling stops immediately */
Copy the code
The solution
1. Add the scroll touch method to the scroll container
Set -webkit-overflow-scrolling to touch
.wrapper {
-webkit-overflow-scrolling: touch;
}
Copy the code
Container ::-webkit-scrollbar {display: none; }
May result in position:fixed; Fixed positioned elements that scroll along with the page
2. Set the overflow
Set the external overflow to Hidden and the content element overflow to Auto. The inner element beyond the body produces a scroll, and the part beyond the body is hidden.
body {
overflow-y: hidden;
}
.wrapper {
overflow-y: auto;
}
Copy the code
A combination of the two is better!
2. IOS pull-up boundary pull-down appears white blank
performance
Hold your finger on the screen and pull it down to create a white area at the top of the screen. Hold your finger on the screen and pull, creating a white area at the bottom.
The reasons causing
In iOS, holding a finger and dragging it up and down triggers the TouchMove event. This event triggers the entire WebView container, which will naturally be dragged, leaving the rest blank.
The solution
1. Do not slide listening events
There are three touch events on the mobile terminal, which are defined as
1.touchStart: Place your finger on a DOM element.2.touchMove: Drag a DOM element with your finger.3.touchend: Remove the finger from a DOM element.Copy the code
Obviously what we need to control is the TouchMove event
touchmove
The speed of events is implementation-definable, depending on hardware performance and other implementation details
preventDefault
Method to block all default behavior on the same touch, such as scrolling.
Therefore, we found a solution. By listening to TouchMove, we made it possible to slide where it was needed and forbidden to slide where it was not needed.
It is important to note that we filter out elements that have scroll containers.
The implementation is as follows:
document.body.addEventListener('touchmove'.function(e) {
if(e._isScroller) return;
// Block the default event
e.preventDefault();
}, {
passive: false
});
Copy the code
2. Scroll to compromise to fill in the blanks and decorate into other features
In many cases, we can stop trying to solve this problem and start thinking about it. Depending on the scenario, we can use the drop-down as a functional operation.
For example: refresh the page after the drop-down
3. The page enlarges or reduces the uncertain behavior
performance
Double-click or open the finger page element with both fingers to zoom in or out.
The reasons causing
HTML itself generates zooming in and out behavior, such as in a PC browser, where pages can be zoomed in and out freely. But on mobile, we don’t need this behavior. Therefore, we need to prohibit this uncertain behavior to improve the user experience.
Principles and solutions
The HTML meta meta tag standard has a medium viewPort property that controls the zoom of a page. It is usually used on mobile devices. Described in MDN in the following figure
<meta name="viewport" content="width=device-width.initial-scale=1.0">
Copy the code
So maximum-scale, minimum-scale, and user-scalable=no can be used 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">
Copy the code
Prevents page enlargement (when meta doesn’t work)
window.addEventListener(
"touchmove".function (event) {
if(event.scale ! = =1) { event.preventDefault(); }}, {passive: false});Copy the code
4. Click event delay and penetration
performance
Listen for element click event, click element trigger time delay is about 300ms.
Click on the mask layer, after the mask disappears, the lower element clicks trigger.
The reasons causing
Why is there a click delay?
In safari on iOS, to double – click zoom operation, click 300ms later, if the second click is not performed, click operation. That is, to determine whether the user’s behavior is caused by a double click. However, in the App, a click creates a 300ms delay whether or not you need to double click to zoom.
Why does click penetration occur?
When a two-layer element is stacked, the touch event is bound to the upper element and the click event to the lower element. Since click occurs after touch, clicking on the upper element causes the element to disappear, and the lower element triggers the click event, creating the click-through effect.
Principles and solutions
Solution 1: Replace Click with TouchStart
As mentioned earlier, mobile devices support not only clicks, but also several touch events. So the basic idea here is to use the Touch event instead of the click event.
Replacing click with TouchStart not only solves the click event delay problem, but also solves the penetration problem. Because penetration problems occur when touch and click are mixed.
Used in native
el.addEventListener("touchstart".() = > { console.log("ok"); }, false);
Copy the code
Used in VUE
< button@touchStart ="handleTouchstart()"> click </button>Copy the code
Open source solutions also provide both click and TouchStart events. Such as the Button component in vant
So, is it possible to putclick
The events are all replaced bytouchstart
? Why are open source frameworks still givenclick
The event?
We imagine a scene that requires clicking and swiping at the same time. What happens if you replace click with touchStart?
Event trigger sequence: TouchStart, TouchMove, TouchEnd, click.
It’s easy to imagine that when I need to swipe touchMove, the touchStart click event is preferentially triggered. Is there already a conflict?
So, in the case of scrolling, the click handle is recommended.
This is also done in the following FastClick open source library.
The main purpose is to ensure that the click event is not under the scrolling parent when synthesized using TouchStart.
Solution 2: Use the FastClick library
Use NPM or YARN after installation
import FastClick from 'fastclick';
FastClick.attach(document.body, options);
Copy the code
Also, with the Fastclick library, click latency and penetration issues are eliminated
In my general practice, when it comes to open source libraries, it’s important to understand how it works. It is mainly to encapsulate the existing native event set into a strong compatibility event set.
Fastclick source code core code is not long, less than 1000 lines. Have interest can understand!
5. The soft keyboard will top up the page and put it away without falling back
performance
On Android phones, when you click on the Input box, the keyboard pops up and pops up the page, causing the page style to mess up.
When the focus is removed, the keyboard is folded up and the keyboard area is blank without falling back.
The reasons causing
We’re going to have a fixed bottom in our app layout. On some versions of Android, typing in a popup will extract the absolute and fixed elements. Resulting in a smaller viewable area, layout confusion.
Principles and solutions
Plan 1:
Listen for input out of focus events, which fall out of focus
/iphone|ipod|ipad/i.test(navigator.appVersion) &&
document.addEventListener(
"blur".(event) = > {
// execute only when the page does not have a scroll bar, because this problem does not occur when there is a scroll bar
// The input textarea tag is executed because a tags also trigger blur events
if (
document.documentElement.offsetHeight <= document.documentElement.clientHeight &&
["input"."textarea"].includes(event.target.localName)
) {
document.body.scrollIntoView(); / / back to the top}},true
);
Copy the code
Scheme 2:
Soft keyboard will page up the solution, mainly by listening to the page height changes, forced to return to the height before the pop-up.
// The height attribute should be changed to style
// 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 the height of the content area
// const container = document.getElementById("container")
Container. Style. height = originalHeight;}}Copy the code
The problem of keyboard not falling back appears in iOS 12+ and wechat 6.7.4+, which is a common Bug in the development of wechat H5.
Compatibility principle, 1. Determine version type 2. Change the scrolling visual area
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+ or wechat 6.7.4+, restore the original viewport
if (+wechatVersion.replace(/\./g.' ') > =674 && +version[1] > =12) {
window.scrollTo(0.Math.max(document.body.clientHeight, document.documentElement.clientHeight)); } Duplicate codeCopy the code
Window.scrollto (x-coord, y-coord), where window.scrollto (0, clientHeight) restores to the original viewport
6. IPhone X series security zone adaptation problem
performance
On both sides of the bangs or at the bottom of the head, bangs block the text, or blank areas with black or white background.
The reasons causing
The iPhone X and its successors all feature bangs and gestures across the screen. The head, bottom and sides all need special treatment. In order to adapt to the special circumstances of iPhone X.
The solution
Set security zones and fill dangerous zones. Do not perform operations or display contents in dangerous zones.
Danger area Finger irregularity area, bottom bar area, left and right trigger area.
The specific operation is viewport-fit,meta tag is set to cover, and all regions are filled. Determine whether the device belongs to iPhone X and add an adaptive 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 rectangle embedded.cover
: View ports are scaled to populate the device display. Highly recommended usesafe area inset
Variable to ensure that important content does not appear outside the display.
Set the viewport – fit tocover
<meta name="viewport" content="width=device-width.initial-scale=1.0, user-scalable=yes, viewport-fit=cover">
Copy the code
Add an adaptive 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); }}/* iPhoneX padding the footer padding-bottom 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); }}Copy the code
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 top, right, bottom, and left rectangles inside the viewport edge so that content can be safely placed without the risk of being cut off by a non-rectangular display.
For a rectangular viewport, such as a regular laptop monitor, the value is zero.
For non-rectangular displays (such as round dials, iPhoneX screens), all content is visible within the rectangle formed by the four values set by the user agent.
Env (
,
?) , the first parameter is the custom region, and the second parameter is the alternate value.
Var () : var(
,
?) Is used to give an alternate value if env() is not in effect.
Constant () was drafted by CSS 2017-2018 and it is unknown whether it has been standardized. It is unknown whether this function is available in other iOS browser versions, but added for compatibility purposes.
See resources at the end of this article for details.
7. The page becomes a problem with pictures and QR codes
performance
There is a need to generate pictures or TWO-DIMENSIONAL code on the page at work. Probably the first thing that comes to mind is that it’s easier to hand it over to the back end. But in this way, we need to pass all the page code to the back end, which consumes too much network performance.
The solution
Generate qr code
Generate a QRCode using QRCode
import QRCode from 'qrcode';
// Use async to generate images
const options = {};
const url = window.location.href;
async url => {
try {
console.log(await QRCode.toDataURL(url, options))
} catch (err) {
console.error(err); }}Copy the code
Assign await qrcode.todataURL (URL, options) to the image URL
Generate images
HtmlToCanvas is mainly used to generate canvas canvas
import html2canvas from 'html2canvas';
html2canvas(document.body).then(function(canvas) {
document.body.appendChild(canvas);
});
Copy the code
But it’s not just here, because it’s canvas. Mobile generated images are blurry.
We use a new canvas method to generate multiple times and put it into a double container to achieve a clearer effect. It is simply realized by downloading pictures and files through hyperlink, and a more complete implementation method will be updated later
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 via the hyperlink
document.querySelector(".btn").setAttribute('href', canvas.toDataURL());
}
Copy the code
Set the scaleSize size as required
8. Wechat public account sharing problems
performance
In the development of wechat public account H5, click the share button inside the page to invoke SDK, but the method does not take effect.
The solution
Add a layer of mask for sharing guidance.
Because click the share button inside the page cannot be called directly, and the share function needs to click more in the upper right corner to operate.
9.H5 invokes sdK-related solutions
Native communication with H5
The solution
Support iOS and Android with DSBridge
See Resources for documentation
The SDK team provides the method
- Registration method
bridge.register
bridge.register('enterApp'.function() {
broadcast.emit('ENTER_APP')})Copy the code
- The callback method
bridge.call
export const getSDKVersion = () = > bridge.call('BLT.getSDKVersion')
Copy the code
Event listening and triggering methods
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
Copy the code
Note on pit
Before calling a method, make sure that the SDK provides the method. If Android provides the method, iOS calls will show a popup window such as method call failure. How do you solve it?
Provide a check whether Android, iOS. Judge according to the device
export const hasNativeMethod = (name) = >
return bridge.hasNativeMethod('BYJ.' + name)
}
export const getSDKVersion = function() {
if (hasNativeMethod('getSDKVersion')) {
bridge.call('BYJ.getSDKVersion')}}Copy the code
The same function requires the same iOS and Android method name, so it is easier to handle oh
10.H5 Debug related scheme policies
performance
Debugging code is generally about looking at data and locating bugs. There are two scenarios, one is debugging during development and testing, and the other is debugging in production environment.
Why is there debugging on production? There are times when this bug cannot be replicated in the test environment and the test environment is inconsistent with the production environment, requiring urgent production debugging.
While developing on the PC side, you can simply drop out of the console and use the tools provided by the browser to operate DevTools or view the logs. But what do we do inside the App?
Principles and solutions
1. vconsole
Console plug-in
It’s easy to use
import Vconsole from 'vconsole'
new Vconsole()
Copy the code
Interested in seeing the fundamentals of its implementation, the point we should focus on is how vsConsole prints out all our logs for Tencent open source Vconsole
The above methods are for development and testing purposes only. It is not allowed in the production environment, so you need to judge the environment when using it.
import Vconsole from 'vconsole'
if(process.env.NODE_ENV ! = ='production') {
new Vconsole()
}
Copy the code
2. Agent + Spy – Debugger
It’s a little bit tricky to do, but I’ll write it out in detail, basically in 4 steps
- Installing plug-ins (global installation)
sudo npm install spy-debugger -g
Copy the code
- Mobile phone and computer under the same wifi, mobile phone set agent
Set the HTTP proxy IP address of the mobile phone to the IP address of the PC and the port to the spy-Debugger startup port
Spy – Debugger default port: 9888
Android: Settings – WLAN – Long press Select Network – Modify Network – Advanced – Proxy Settings – Manual
IOS: Settings – Wi-Fi – Select the network, click the exclamation mark, HTTP proxy manual
- Open the H5 page in the browser or APP
- Open the desktop log site for debugging and click on the NPM console to listen for the address. View the packet capture and H5 page structure
This approach allows you to debug the generated environment’s pages without modifying the code and can handle most debugging requirements
Reference: small lock jun less
12 mobile terminal 100vh problems
Problem Description:
Full screen scrolling is required on scrolling phones (swiper is used). The 100vh layout is used because the height of the mobile terminal is variable, which is very harmonious in the simulator. As a result, the browser bar and some navigation bar title bar appear differently in Chrome and wechat/Safari browsers on mobile terminals
Presentation 1: The swiper plugin is set to innerHeight, causing a fault in the scrolling of the wechat browser
Rendering 2:100vh is actually too high for the screen, causing some content to be blocked
Causes of occurrence:
It’s best to avoid 100vh and instead rely on javascript to set the height for a complete viewport experience.
The core problem is that mobile browsers (Chrome and Safari) have a “help” feature that makes the address bar sometimes visible and sometimes hidden, changing the size of the viewport,
Instead of making the height of 100vh visible on the screen when the viewport height changes, these browsers set 100vh to the height of the browser that hides the address bar. As a result, the bottom part of the screen will be cut off when the address bar is visible, destroying the purpose of 100Vh.
A 3:
When we use the iOS Safari browser, the toolbar and address bar are hidden when we swipe the page.
When the page slides up, the toolbar is hidden and the window.innerHeight changes, but the CSS VH does not change. 100vh = window.innerHeight when the toolbar is hidden. (on IphoneXR, window.innerHeight = 719px with toolbar displayed and window.innerHeight = 833px with toolbar hidden)
It doesn’t matter if your page is designed to be a long slide, but if your page is designed to be a single-page application the size of a viewport, that’s a problem. Because even if you set width to 100%, the page will still scroll, and when you scroll up to a certain threshold, the toolbar will hide and the layout will be completely confused. And the height of the toolbar is different in landscape and portrait.
Also, if we set the absolute or fixed attribute to an element and want to fix it to the bottom, Safari doesn’t do that either. As mentioned above, part of your page is actually blocked by the toolbar at the bottom, so the elements we put at the bottom will also be blocked by the toolbar.
Some solutions:
1. Use calc to dynamically calculate height of objects blocked by nav (not tried)
min-height: calc(100vh - 0.9 rem) / /0.9 remIt's the height of the obstructionCopy the code
2. Use js to dynamically set the height
Setting the height to window.innerHeight correctly sets the height to the visible part of the window. If the address bar is visible, window.innerHeight is the height of the full screen. If the address bar is hidden, window.innerHeight is the height of the visible part of the screen,
3. Use it in VUE projects
${app}/src/app.vue
mounted() {
// First we get the viewport height and we multiple it by 1% to get a value for a vh unit
let vh = window.innerHeight * 0.01
// Then we set the value in the --vh custom property to the root of the document
document.documentElement.style.setProperty('--vh'.`${vh}px`)
// We listen to the resize event
window.addEventListener('resize'.() = > {
// We execute the same script as before
let vh = window.innerHeight * 0.01
document.documentElement.style.setProperty('--vh'.`${vh}px`)})},Copy the code
${app}/views/foo.vue
<style lang="scss" scoped>
.container {
height: 100vh; /* Previously set to 100vh, compatible with some browsers that do not support custom attributes. * /
height: calc(var(--vh, 1vh) * 100 - 46px);
</style>
Copy the code
Use 4.height:100%
Set each level below the body to a height of 100%
* {
padding: 0;
margin: 0;
border: 0;
outline: 0;
box-sizing: border-box;
}
html {
width: 100%;
height: 100%;
border: 5px solid red;
overflow: hidden;
// We will try it tomorrow
height:-webkit-fill-available;
}
Copy the code
5. Dynamically resolve the height in MAC Browser, using CSS
The toolbar height is 75px, and calc’s calculated properties are not compatible with earlier versions of Safari
Set each level below the body to a height of 100%
calc(100vh - 75px)
Copy the code
6. Content collapse caused by the lack of parent container height and child height: 100%
Scenario Description:
<head> <style> .app { width: 100%; height: 100%; display: flex; flex: 1; flex-direction: column; } header { width: 100%; height: 75px; } main { flex: 1; } iframe { width: 100%; height: 100%; } </style> </head> <body> <div class="app"> <header></header> <main> <iframe v-if="true"></iframe> <div v-else></div> </main> </div>Copy the code
The parent of an element with a percentage height must have a defined height and must have the height attribute. Otherwise elements with percentage height must default to height: auto(content height)
Chrome automatically fixes this problem, but Safari considers it a bug where the parent of the iframe does not have a given height, causing the iframe height to collapse (along with the content height). So when you stretch the browser window, the actual height of the iframe content changes, causing this problem.
Solution:
- Specifies the height of the parent
main { flex: 1; height: calc(100% - 75px); } height: calc(100vh - calc(100vh - 100%))Copy the code
- Specify the height of the iframe child directly
iframe { width: 100%; height: calc(100vh - 75px); }
Copy the code
We don’t use 100%-75px because it is 100% dependent on the height specified by the parent, whereas VH is based directly on the browser window height.
7. Use – its – fill – the available
It’s no use (safari)
The CSS
body {
min-height: 100vh;
/* mobile viewport bug fix */
min-height: -webkit-fill-available;
}
html {
height: -webkit-fill-available;
}
body {
display: flex;
flex-direction: column;
margin: 0;
min-height: 100vh;
}
main {
flex: 1;
}
Copy the code
8. The perfect solution
<template>
<div class="module">
<div class="module__item">20%</div>
<div class="module__item">40%</div>
<div class="module__item">60%</div>
<div class="module__item">80%</div>
<div class="module__item">100%</div>
</div>
</template>
<script>
export default {
mounted() {
// First we get the viewport height and we multiple it by 1% to get a value for a vh unit
const vh = window.innerHeight * 0.01
// Then we set the value in the --vh custom property to the root of the document
document.documentElement.style.setProperty('--vh'.`${vh}px`)
// We listen to the resize event
window.addEventListener('resize'.() = > {
// We execute the same script as before
const vh = window.innerHeight * 0.01
document.documentElement.style.setProperty('--vh'.`${vh}px`)}}}</script>
<style>
body {
background-color: # 333;
}
.module {
height: 100vh; /* Use vh as a fallback for browsers that do not support Custom Properties */
height: calc(var(--vh, 1vh) * 100);
margin: 0 auto;
max-width: 30%;
}
.module__item {
align-items: center;
display: flex;
height: 20%;
justify-content: center;
}
.module__item:nth-child(odd) {
background-color: #fff;
color: #f73859;
}
.module__item:nth-child(even) {
background-color: #f73859;
color: #f1d08a;
}
</style>
Copy the code
13 Safari problems
1. The high default value of the Input tag in Safari
In browser compatibility, the default value of the input tag in Safari is always set to the same height.
If Safari’s input height doesn’t work, be sure to set line-height and remove the iOS UI style: -webkit-appearance: None;
14 Flex Layout Problems (Extensions)
Each unit block in the container is called a Flex item
Spindle space :main size
Cross axis space :cross size
1. The flex container
div{ display: flex | inline-flex; }
Copy the code
When the Flex layout is set, the float, clear, and vertical-align attributes of the child elements are invalidated.
Flex :1’s div height ADAPTS to the remaining height of the screen
2. Set six properties for the Flex container
1. Flex-direction: determine the direction of the main axis (i.e. the alignment of items)
.container {
flex-direction: row(the default) | row - reverse | column | column - reverse; }Copy the code
2. Flex-wrap: Determines whether items in the container can be wrapped
.container {
flex-wrap: nowrap(the default) |wrap(project spindle overall size beyond the container line, the first line at the top) | wrap - reverse; (reverse)}Copy the code
- Flex-flow: short for flex-direction and flex-wrap (useless)
4. Justify -content: Defines the alignment of items on the main axis.
.container {
justify-content:
flex-start(the default value Left-aligned) |flex-end(right) | center |space-between(full-justified, only two rows, respectively in the fore and aft) |space-around(each project on both sides of the equal interval, projects than the interval between twice with the edge of the interval) | space - evenly child elements will be evenly distributed in the container, at the same time the extra space will quilt elements on either side of the share}Copy the code
Remember that context-content only works if the box has space left to allocate.
5. Align-items: Defines the alignment of items on the cross axis
.container {
align-items:
stretch(Default): If the item is not set to height or is set to Auto, it will take up the entire container height. Flex-start center baseline flex-end Center baseline baseline}Copy the code
6. Align-content: Defines the alignment of multiple axes. This property will not work if the project has only one axis
.container {
align-content: flex-start | flex-end | center | space-between | space-around | stretch(Default value); }Copy the code
When you flex-wrap is set to NowRAP, there is only one axis in the container, and since the project does not wrap, there will be no multiple axes.
When flex-wrap is set to wrap, the container will have multiple axes and you will need to set the alignment between the axes.
Align as justify-content ends/middle/isometric, etc
Flex project properties
1. Order: Defines the order of items in the container. The smaller the value, the higher the order
Order is set so that it can be ranked first.
2. Flex-basis: defines how much space the project occupies on the main axis before allocating extra space. Based on this property, the browser calculates whether there is extra space on the main axis
Default: auto, which is the size of the item, depending on the width or height of the item.
When the main axis is horizontal, the project width is invalidated when flex-basis is set. Flex-basis needs to be used in conjunction with Flex-grow and Flex-shrink to be effective.
- When the flex-basis value is 0 %, the project is considered zero-sized, so declaring the size 140px is not helpful.
- When the flex-basis value is auto, then the size is set (say 100px) and the 100px will not be included in the remaining space.
3. Flex-grow: Defines the scale of the project
The default value is 0, that is, if there is free space, it is not enlarged
Flex-grow comes into play when there is still space left after all the items have been sorted with flex-basis values.
If all projects have a flex-Grow attribute of 1, they divide the remaining space equally. (If any)
If one project has a flex-grow attribute of 2 and all the other projects are 1, the former takes up twice as much free space as the other items.
Of course, if you run out of space after all the items are sorted by flex-basis and flex-wrap: nowrap, flex-grow will no longer work, then you need this property.
4. Flex-shrink: Defines the size of the project
Default value: 1, that is, the item will shrink if there is insufficient space. Negative values do not apply to this property.
If the flex-shrink attribute is 0 for one project and 1 for all other projects, the former does not shrink when space is insufficient.
5. Flex: short for flex-grow, flex-shrink and flex-basis
.item{
flex: <'flex-grow'> <'flex-shrink'>? || <'flex-basis'>]0 1 auto(Default)}Copy the code
They are as follows:
1. If flex is a non-negative number, the number is flex-grow, flex-shrink is 1, and Flex-basis is 0%
.item {flex: 1; } (Divide the remaining space equally)/ / equivalent to the
.item {
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0%;
}
Copy the code
2. When the flex value is 0, the corresponding three values are 0 1 0%
.item {flex: 0; }(There is residual space, and no amplification)/ / equivalent to the
.item {
flex-grow: 0;
flex-shrink: 1;
flex-basis: 0%;
}
Copy the code
Finally, I beg youattention
~~~ I will always try to update!! Be a qualified porter [laughs
This article references many excellent articles by other big names ~ some reference links may not be pointed out but be sure to fill in any omissions ❤
(*^▽^*) In the next chapter, I would like to share with you the answers to the most frequently asked questions in recent interviews.