author | content | time |
---|---|---|
JJ | Mixed development problem | 20220117 |
Style adaptation problem
The same page and the same element show the two patterns on the left and right (the resolution of Huawei mate30pro is 1176 * 2400, and the width unit is rem).
Let's think about it. Why is there this problem?
Extend it
Pixel classification: device pixels and CSS pixels
- Device independent pixels: the physical pixels of the device screen. The number of physical pixels of any device is fixed
- CSS pixels: also known as logical pixels, it is an abstract layer created for web developers and used in CSS and javascript
- Every CSS declaration and almost all javascript attributes use CSS pixels, so device pixels are never actually used.
On the desktop side, a pixel of css often corresponds to a physical pixel of the computer screen.
On the mobile phone, due to the limitation of screen size, zooming is a frequent operation.
When zooming out, one device pixel covers multiple CSS pixels
When zooming in, one CSS pixel covers multiple device pixels
The CSS pixels (such as width:300px) set by the element are always the same regardless of reduction or enlargement, and the number of device pixels corresponding to a CSS pixel is determined according to the current zoom scale.
We have to mention the viewport in HTML. We often set the width of the viewport = device width. What is the value of the device width?
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"/>
Device width = 320 for iPhone 5, 375 for iPhone 6 and 414 for iPhone 6 +.
DPR:
Device pixel ratio DPR(devicePixelRatio)Yes, the default zoom is 100%In the case of device pixels and CSS Pixel ratio
dpr, also known as device pixel ratio, is the ratio of physical pixels to logical pixels, which is not difficult to understand: dpr=2 under iPhone 6 and dpr=3 under iPhone 6 + (considering the pixels in rasterization, not real physical pixels;
Cause of problem:
Due to the Huawei browser version problem, the minimum pixel supported by the low version of Huawei browser is 12px, while the high version is unlimited.
How to avoid similar problems:
Postcss pxtorem and flexible
Postcss pxtorem function: convert px to rem
flexible function: calculate the root font size( flexible.js )
Usage of postcss pxtorem:
main.js
// flexible is introduced to set the benchmark value of rem import 'lib-flexible/flexible.js';
.postcssrc.js configuration
module.exports = { "plugins": { "postcss-import": {}, "postcss-url": {}, // to edit target browsers: use "browserslist" field in package.json "autoprefixer": {}, 'postcss-pxtorem': { rootValue({ file }) { return file.indexOf('vant') !== -1 ? 37.5 : 117.6;(width/10) }, "propList": ['*'], "selectorBlackList": ['.norem'] // Filter it out Classes beginning with norem are not converted } } }
1px border (vant)
<!-- border-top --> <div class="van-hairline--top"></div>
Mobile 1px implementation scheme( https://zhuanlan.zhihu.com/p/100752129 )
performance optimization
Route lazy loading
1, Definition
Lazy loading simply means delayed loading or on-demand loading, that is, loading when needed.
2, Writing method
There are two common lazy loading methods: using vue asynchronous components and import ing in ES
Unloaded writing method: import index from '@/pages/index/index.vue'; Lazy loading method 1: const index = () => import('@/pages/index/index.vue'); routes: [ { path: '/', name: 'index', component: index }] Lazy loading method 2 routes: [ { path: '/', name: 'index', component: resolve=>(require(["@/pages/index/index.vue"],resolve)) }]
3, Difference after packaging
The js folder in dist package was not loaded lazily
Modify to lazy load js folder in dist package
Picture compression( https://tinypng.com/ )
Open gzip
1, Disposition
config/index.js/productionGzip: true (the packaging effect is shown in the figure above)
2, Effect
When the HTML document is parsed, DOMContentLoaded will be triggered, and the load event will not be triggered until all resources are loaded. The $(document) often used in jQuery Ready (function() {/ /... Code...}); In fact, the DOMContentLoaded event is monitored, and $(document) Load (function() {/ /... Code...}); The load event is monitored.
3, Using Android shell cdr cache
Components load on demand
1, vant load on demand
2, Ecarts load on demand
main.js
Use cdn cache (network restrictions not used)
1, Resource introduction
In index HTML, add CDN resources, such as those on bootstrap:
<body> <div id="app"></div> <script src="https://cdn.bootcss.com/vue/2.5.2/vue.min.js"></script> <script src="https://cdn.bootcss.com/vue-router/3.0.1/vue-router.min.js"></script> </body>
2, Add configuration
In bulid / webpack base. Add externals in conf.js file to import the referenced external module, as follows:
module.exports = { entry: {app: './src/main.js'}, externals:{'vue': 'Vue','vue-router': 'VueRouter'} }
3, Remove the original reference
Remove import and Vue Use (xxx), etc
// import Vue from 'vue' // import Router from 'vue-router' // Vue.use(Router)
Interactive optimization
1, Increase timeout
ajax.js,
ajax.defaults.timeout = 10000;
2, Add timeout prompt
ajax.js post interceptor error, added
if (error && error.stack.indexOf('timeout') > -1) { Toast.fail({message: 'The connection timed out. Please check your network'});} else if (error && error.stack.indexOf('Network Error') > -1) { Toast.fail({ message: 'The current network is unavailable. Please check your network'}); }
Weixin JS SDK usage
npm i -S weixin-js-sdk
use
//introduce import wx from 'weixin-js-sdk'; //Request interface to get jsapi_ticket const params = { //Current page url url:location.href.split('#')[0], //Random string noncestr:Math.random().toString(36) .substr(2, 15), //time stamp timestamp:parseInt(new Date().getTime() / 1000) }; //Register after the interface returns the bill wx.config({ debug: false, appId: 'wld341060039', timestamp:params.timestamp, nonceStr: params.noncestr, signature: res.ticket, //Register events select photos / take photos to get local photo data jsApiList: ['chooseImage', 'getLocalImgData'] }); // Successful verification is processed through the ready interface wx.ready(function () { console.log(666); }); // Failed to process validation through the error interface wx.error(function (res) { console.log('error', res); }); // Judge whether the current client version supports the specified JS interface wx.checkJsApi({ // List of JS interfaces to be tested. See Appendix 2 for the list of all JS interfaces, jsApiList: ['chooseImage', 'getLocalImgData'], success: function (res) { console.log(res); // It is returned as a key value pair. The available api value is true and the unavailable api value is false // For example: {"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"} } });
Take a picture or select a picture interface from your phone's photo album
wx.chooseImage({ count: 1, // Default 9 sizeType: ['original', 'compressed'], // You can specify whether to use the original or compressed image. Both are available by default sourceType: ['album', 'camera'], // You can specify whether the source is an album or a camera. Both are available by default quality: 0.8, //The compression quality ranges from 0 to 1. The smaller the value, the lower the quality and the higher the compression rate (only valid for jpg) success: function (res) { // Returns the local ID list (absolute path) of the selected photo. The local ID can be used as the src attribute of the img tag to display the picture var localIds = res.localIds; } });
Get local picture interface
wx.getLocalImgData({ localId: '', // localID of the picture success: function (res) { //localData is the base64 data of the picture, which can be displayed with the img tag let localData = res.localData; //ios compatibility with Android if (localData.indexOf('data:image') != 0) { // Determine whether there is such a head localData = `data:image/jpeg;base64,${localData}`; } localData = localData.replace(/\r|\n/g, '').replace('data:image/jgp', 'data:image/jpeg'); } });
ios compressed picture problem
Image compression method
cutImageBase64(base64, w, callback) { const newImage = new Image(); let quality = 0.6; // Compressibility between 0-1 newImage.src = base64; newImage.setAttribute('crossOrigin', 'Anonymous'); // Required when the url is a foreign domain let imgWidth, imgHeight; newImage.onload = function () { imgWidth = this.width; imgHeight = this.height; const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); if (Math.max(imgWidth, imgHeight) > w) { if (imgWidth > imgHeight) { canvas.width = w; canvas.height = w * imgHeight / imgWidth; } else { canvas.height = w; canvas.width = w * imgWidth / imgHeight; } } else { canvas.width = imgWidth; canvas.height = imgHeight; quality = 0.6; } ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.drawImage(this, 0, 0, canvas.width, canvas.height); let base64 = canvas.toDataURL('image/jpeg', quality); // Compression statement // If you want to ensure that the picture is compressed to the size you want, if it is required to be between 50-150kb, please add the following statement. The initial value of quality is determined according to the situation while (base64.length / 1024 > 150) { quality -= 0.01; base64 = canvas.toDataURL('image/jpeg', quality); } // Prevent the last compression from falling below the minimum size, as long as the decrease in quality is reasonable, it does not need to be considered while (base64.length / 1024 < 50) { quality += 0.001; base64 = canvas.toDataURL('image/jpeg', quality); } // It must be returned through the callback function, otherwise the value cannot be obtained in time callback(base64); }; }
Use compressed pictures
this.cutImageBase64(base64, 700, this.uploadImgbas);
Compressed data
uploadImgbas(base64) { console.log(base64)}
ios considerations
In IOS, canvas drawing pictures has two limitations:
the first is the size of the picture. If the size of the picture exceeds 2 million pixels, the picture cannot be drawn on the canvas. There will be no error when calling drawImage, but when you use toDataURL to obtain picture data, you get empty picture data.
moreover, the size of the canvas is limited. If the size of the canvas is greater than about 5 million pixels (i.e. the width height product), not only the picture can not be drawn, but also anything else can not be drawn.
in response to the above two restrictions, I control the image width and height compression within 1000px, so that the maximum image does not exceed 2 million pixels. In front-end development, 1000px*1000px can basically meet most of the needs. Of course, there is a more perfect tile drawing method. Let's say tile drawing method here.
in this way, the two limitations on IOS are solved.
In addition to the above limitations, there are two pitfalls. One is that the toDataURL of canvas can only compress jpg. When the image uploaded by the user is png, it needs to be converted to JPG, that is, canvas toDataURL ('image/jpeg ', 0.5), the type is uniformly set to JPEG, and the compression ratio is controlled by itself.
The other is that if png is converted to JPG and there is a transparent area in the canvas when drawing on the canvas, the transparent area will turn black when converting to jpg. Because the transparent pixel of the canvas is rgba(0,0,0,0), it will become RGBA (0,0,1) when converting to JPG, that is, the transparent background will turn black. The solution is to lay a white background on the canvas before drawing.