自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

手寫(xiě)Flexible.js的原理實(shí)現(xiàn),我終于明白移動(dòng)端多端適配

開(kāi)發(fā) 前端
今天在看阿里的面試題時(shí),看到這樣一道面試題,問(wèn)Flexible.js的原理是什么?簡(jiǎn)單的一句概括就是:Flexible.js幫我們計(jì)算出1rem 等于多少px。

今天在看阿里的面試題時(shí),看到這樣一道面試題,問(wèn)flexible.js的原理是什么?

圖片

然而我也不知道,但是剛好我又在我公司的項(xiàng)目上遇到過(guò),于是研究一番,遂作此文。

核心原理

簡(jiǎn)單的一句概括就是:flexible.js幫我們計(jì)算出1rem 等于多少px。

怎么計(jì)算的?

很簡(jiǎn)單,就是1rem = 屏幕寬度的1/10.

var docEl = document.documentElement  // 返回文檔的root元素,即html
var rem = docEl.clientWidth / 10
docEl.style.fontSize = rem + 'px'

我們知道rem的大小是根據(jù)html節(jié)點(diǎn)的font-size的相對(duì)值。

例如,iphone 6的屏幕寬度為375px,因此1rem === 37.5px。

計(jì)算rem干嘛?

那幫我們計(jì)算出rem的值有什么鬼用嗎?

確實(shí),如果只是單純的計(jì)算出rem的值并沒(méi)什么用。發(fā)揮它的用處是當(dāng)我們根據(jù)設(shè)計(jì)稿來(lái)轉(zhuǎn)化成頁(yè)面時(shí)需要用到。

舉個(gè)例子,現(xiàn)在有兩個(gè)手機(jī),一個(gè)手機(jī)的屏幕寬度是375px,一個(gè)是750px,設(shè)計(jì)稿給我們的寬度是375px,那我們按照設(shè)計(jì)稿的設(shè)計(jì)在375px的手機(jī)上剛好完美匹配,但是卻會(huì)發(fā)現(xiàn)在750px的手機(jī)上頁(yè)面只有一半,空白了一半。

這就是我們需要解決的問(wèn)題,即怎么解決移動(dòng)端尺寸眾多的問(wèn)題,我們的設(shè)計(jì)稿是固定,怎么辦,如果設(shè)計(jì)稿是彈性的可以隨意縮放該多好。

好吧,設(shè)計(jì)只給一張?jiān)O(shè)計(jì)稿,我們只能想其他方法啦。

等比畫(huà)餅

想想,有辦法了,就像本來(lái)你在一張大的紙上面了一餅,現(xiàn)在讓你在小的紙上在畫(huà)一次要怎么畫(huà),就是所有東西都等比例畫(huà)小,如果要畫(huà)到更大的紙上也是一個(gè)道理,等比畫(huà)大,對(duì)不對(duì)。

現(xiàn)在我們把設(shè)計(jì)稿分成10等份,設(shè)計(jì)稿 A = W/10,我們把設(shè)備可視區(qū)域也就是我們的各種移動(dòng)端設(shè)備的這個(gè)畫(huà)布也分成10份,并賦值給根元素的fontSize,我們都知道rem是根據(jù)根元素字體大小計(jì)算的,所以我們的1rem也就是設(shè)備可視區(qū)域/10,現(xiàn)在設(shè)計(jì)稿上有一塊區(qū)域?qū)払,那它是不是等比放到設(shè)備可視區(qū)域的寬度為 B/A rem。

再啰嗦一下,B在設(shè)計(jì)稿上占B/A份,那在設(shè)備可視區(qū)域上也要占B/A份對(duì)不對(duì),所以寬是B/A rem。這就是flexible.js能實(shí)現(xiàn)設(shè)備兼容的原理。下面看代碼。

// 首先是一個(gè)立即執(zhí)行函數(shù),執(zhí)行時(shí)傳入的參數(shù)是window和document
(function flexible (window, document) {
var docEl = document.documentElement // 返回文檔的root元素
var dpr = window.devicePixelRatio || 1 // 獲取設(shè)備的dpr,即當(dāng)前設(shè)置下物理像素與虛擬像素的比值

// adjust body font size 設(shè)置默認(rèn)字體大小,默認(rèn)的字體大小繼承自body
function setBodyFontSize () {
if (document.body) {
document.body.style.fontSize = (12 * dpr) + 'px'
}
else {
document.addEventListener('DOMContentLoaded', setBodyFontSize)
}
}
setBodyFontSize();
// set 1rem = viewWidth / 10
function setRemUnit () {
var rem = docEl.clientWidth / 10
docEl.style.fontSize = rem + 'px'
}
setRemUnit()
// reset rem unit on page resize
window.addEventListener('resize', setRemUnit)
window.addEventListener('pageshow', function (e) {
if (e.persisted) {
setRemUnit()
}
})
// detect 0.5px supports 檢測(cè)是否支持0.5像素,解決1px在高清屏多像素問(wèn)題,需要css的配合。
if (dpr >= 2) {
var fakeBody = document.createElement('body')
var testElement = document.createElement('div')
testElement.style.border = '.5px solid transparent'
fakeBody.appendChild(testElement)
docEl.appendChild(fakeBody)
if (testElement.offsetHeight === 1) {
docEl.classList.add('hairlines')
}
docEl.removeChild(fakeBody)
}
}(window, document))

這就是flexible.js的源碼,超級(jí)簡(jiǎn)單吧。

圖片圖片

就這幾行代碼就有12k的star,要是我也早點(diǎn)發(fā)現(xiàn)這個(gè)方案就好了。那star就是我的了。

現(xiàn)在已經(jīng)實(shí)現(xiàn)了將屏幕分為10等份,也就是1rem。

將設(shè)計(jì)稿分成10等份

根據(jù)我們上面畫(huà)餅的方案,現(xiàn)在也要把設(shè)計(jì)稿轉(zhuǎn)化為10等分才行。

我看了下我們項(xiàng)目的實(shí)現(xiàn)是用到了postcss-pxtorem插件來(lái)實(shí)現(xiàn)的。

因?yàn)樵O(shè)計(jì)稿給我們的是px單位的,所以我們?cè)陂_(kāi)發(fā)的時(shí)候只能寫(xiě)px,然后這就需要postcss-pxtorem來(lái)幫我們將我們寫(xiě)的px轉(zhuǎn)化為rem了。

安裝完postcss-pxtorem之后的配合非常簡(jiǎn)單,只要在.postcssrc.js文件配置如下就好了。

module.exports = {
plugins: {
'postcss-pxtorem': {
rootValue: 75,
}
}
}

rootValue:75 為啥是75呢,這是因?yàn)槲覀兊脑O(shè)計(jì)稿的寬度是750px,十分之一就是75px。

圖片圖片

如果你們的設(shè)計(jì)稿是375px的,就需要將值改寫(xiě)成37.5。

flexible.js升級(jí)版

我們公司的使用是在flexible.js的基礎(chǔ)上進(jìn)行了更改,主要是添加了這樣一段代碼。

var metaEl = doc.querySelector('meta[name="viewport"]');
if (metaEl) {
console.warn('將根據(jù)已有的meta標(biāo)簽來(lái)設(shè)置縮放比例');
var match = metaEl.getAttribute('content').match(/initial\-scale=([\d\.]+)/);
if (match) {
scale = parseFloat(match[1]);
dpr = parseInt(1 / scale);
}
}

這一串主要是來(lái)實(shí)現(xiàn)iphone和安卓的設(shè)備像素比不一樣的問(wèn)題,例如iphone的一些手機(jī)。

總結(jié)

就這么簡(jiǎn)單的兩步就實(shí)現(xiàn)了移動(dòng)端的適配。

相關(guān)參考

  • flexible.js 原理解析(看了不會(huì)忘):https://juejin.cn/post/6923060568437817351。
  • 通過(guò)插件postcss-pxtorem輕松實(shí)現(xiàn)px到rem轉(zhuǎn)換,完成移動(dòng)端適配:https://blog.csdn.net/llq886/article/details/105737987。
責(zé)任編輯:姜華 來(lái)源: 前端陽(yáng)光
相關(guān)推薦

2020-08-19 07:54:40

TCP傳輸層協(xié)議

2021-02-15 21:48:37

Python解釋器源碼

2022-05-12 10:36:10

移動(dòng)方案

2018-11-23 09:25:00

TCC分布式事務(wù)

2020-08-06 16:55:37

虛擬化底層計(jì)算機(jī)

2022-06-09 15:53:16

移動(dòng)端渲染GPU

2020-03-20 08:30:56

手機(jī)移動(dòng)端適配

2021-11-19 06:50:17

OAuth協(xié)議授權(quán)

2017-11-13 16:35:36

iPhone X全面屏APP

2011-03-07 13:50:20

2021-07-26 05:00:16

算法DfsBfs

2015-06-30 11:05:11

flexibleWebAPP設(shè)計(jì)

2016-04-11 12:54:18

云適配

2024-04-16 13:56:09

移動(dòng)端安全區(qū)域iOS

2021-12-01 06:40:32

Bind原理實(shí)現(xiàn)

2022-12-31 08:17:02

2019-06-17 08:21:06

RPC框架服務(wù)

2016-01-05 09:45:57

設(shè)計(jì)版式

2020-03-09 09:13:40

HTTPSTCP網(wǎng)絡(luò)協(xié)議

2022-07-06 08:30:36

vuereactvdom
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)