当前位置: 首页 > 科技观察

实现了手写Flexible.js的原理,终于明白移动端的多端适配了

时间:2023-03-20 19:13:23 科技观察

今天在看阿里面试题的时候,看到了这么一道面试题。flexible.js的原理是什么?不过不知道,不过在公司的项目中碰巧又遇到了,于是研究了一下,写了这篇文章。核心原理简单总结就是:flexible.js帮我们计算多少px等于1rem。它是如何计算的?很简单,就是1rem=1/10的屏幕宽度.vardocEl=document.documentElement//返回文档的根元素,即htmlvarrem=docEl.clientWidth/10docEl.style.fontSize=rem+'px'我们知道rem的大小是相对于html节点的font-size的。比如iphone6的屏幕宽度是375px,所以1rem===37.5px。为什么要计算rem?计算rem的值对我们有什么用呢?确实,单纯计算rem的值是没有用的。当我们根据设计稿将其转换为页面时,需要用到它的用处。比如现在有两部手机,一部屏幕宽度为375px,一部屏幕宽度为750px,而设计稿给我们的宽度是375px,那么我们就可以在375px的手机上完美匹配手机按照设计稿,但是会发现在750px的手机上,只留了一半的页面空白。这就是我们要解决的问题,即如何解决移动端的大尺寸问题。我们的设计稿是固定的,怎么办?要是设计稿能灵活一点,可以随意缩放就好了。好吧,设计只是给了一个设计稿,只能想别的办法了。想像画蛋糕一样,有一个办法,就像你原来在一张大纸上做了一个蛋糕,现在又让你在一张小纸上画了一遍,也就是什么都按比例画小,如果你想在更大的纸上画画也是如此,它比画大,不是吗?现在我们把设计稿分成10等份,设计稿A=W/10,我们也把设备可见区域,也就是我们各种移动设备的画布,分成10份,分配给根元素的fontSize,我们都知道rem是根据根元素的字体大小计算的,所以我们的1rem就是设备可见区域/10。现在设计稿上有一个宽度为B的区域,那么它是否与设备可见区域的宽度成正比呢?B/A雷姆。重复一遍,B在设计稿中占有B/A份额,所以在器件可见区域也占有B/A份额,所以宽度为B/Arem。这就是flexible.js实现设备兼容性的方式。看看下面的代码。//第一个是立即执行函数,执行时传入的参数是window和document(functionflexible(window,document){vardocEl=document.documentElement//返回文档的根元素vardpr=window.devicePixelRatio||1//获取设备的dpr,即当前设置下物理像素与虚拟像素的比例//调整body字体大小设置默认字体大小,默认字体大小继承自body函数setBodyFontSize(){if(document.body){document.body.style.fontSize=(12*dpr)+'px'}else{document.addEventListener('DOMContentLoaded',setBodyFontSize)}}setBodyFontSize();//设置1rem=viewWidth/10functionsetRemUnit(){varrem=docEl.clientWidth/10docEl.style.fontSize=rem+'px'}setRemUnit()//在页面调整大小时重置rem单位window.addEventListener('resize',setRemUnit)window.addEventListener('pageshow',function(e){if(e.persisted){setRemUnit()}})//检测0.5px支持检测是否支持0.5像素,解决高清屏1px的多像素问题,需要css的配合。if(dpr>=2){varfakeBody=document.createElement('body')vartestElement=document.createElement('div')testElement.style.border='.5pxsolidtransparent'fakeBody.appendChild(testElement)docEl。appendChild(fakeBody)if(testElement.offsetHeight===1){docEl.classList.add('hairlines')}docEl.removeChild(fakeBody)}}(window,document))这是flexible.js的源码,超级简单的酒吧。仅仅这几行代码就有12k星,要是我早点找到这个解决方案就好了。那颗星是我的现在已经实现了把屏幕分成10等份,也就是1rem。将设计稿分成10等份。根据我们上面的计划,我们需要将设计稿转换成10等份。我使用postcss-pxtorem插件查看了我们项目的实现。因为设计稿是给我们px单位的,所以我们开发的时候只能写px,然后就需要postcss-pxtorem帮我们把写的px转换成rem。安装postcss-pxtorem后的配合很简单,只要将.postcssrc.js文件配置如下即可。module.exports={plugins:{'postcss-pxtorem':{rootValue:75,}}}rootValue:75为什么是75?这是因为我们设计稿的宽度是750px,十分之一是75px。如果你的设计稿是375px,需要改写成37.5。flexible.js的升级版我们公司在flexible.js的基础上做了改动,主要是增加了这么一段代码。varmetaEl=doc.querySelector('meta[name="viewport"]');if(metaEl){console.warn('缩放比例将根据已有的meta标签设置');varmatch=metaEl.getAttribute('content').match(/initial\-scale=([\d\.]+)/);如果(匹配){scale=parseFloat(匹配[1]);dpr=parseInt(1/比例);}}这个系列主要是为了实现iphone和Android的设备像素比例不一样的问题,比如iphone的一些手机。综上所述,移动终端的适配是通过两个简单的步骤实现的。相关参考flexible.js原理分析(看完不会忘记):https://juejin.cn/post/6923060568437817351。通过插件postcss-pxtorem轻松实现px转rem,完成移动端适配:https://blog.csdn.net/llq886/article/details/105737987。