📋 个人简介
- 💖 作者简介:大家好,我是阿牛。😜
前言
我们的移动端布局通常会有rem结合媒体查询的实现,但是,淘宝有这样的一个flexible.js框架,根据不同的width给网页中html根节点设置不同的font-size,大大提高了我们的开发效率,今天阿牛便带你手写一个简易版flexible.js并解读,了解他的大致原理。
flexible.js是什么?
flexible.js手淘框架,是淘宝开发的一个用来适配移动端的js框架。
手淘框架的核心原理就是根据不同的width给网页中html根节点设置不同的font-size,然后所有的距离大小都用rem来代替,这样就实现了不同大小的屏幕都适应相同的样式了。
rem适配布局介绍
rem ( root em )是一个相对单位,类似于 em , em 是父元素字体大小。不同的是 rem 的基准是相对于 htm 元素的字体大小。
比如,根元素( html )设置 font - size =12px;非根元素设置width:2rem;则换成 px 表示就是24px.
rem的优点是可以通过修改html里面的文字大小来改变页面中元素的大小,可以整体控制。
通常在网页布局中,我们可以结合媒体查询+rem实现元素变化,即不同像素的屏幕对应的根html标签的样式font-size的值不同。像下面这样:
@media (min-width:860px){
html{
font-size:50px;
}
}
简易版flexible.js源码分析
(function flexible(window,document){
// 获取html的根元素
var docEl = document.documentElement;
// dpr 物理像素比 window.devicePixelRatio 会获取当前屏幕的物理像素比,如果是pc端则为1,移动端为2。
// 如果当前浏览器没有window.devicePixelRatio则取1
var dpr = window.devicePixelRatio || 1;
// 设置body的字体大小
function setBodyFontSize(){
// 如果页面有body这个元素,就设置body的字体大小
if (document.body){
document.body.style.fontSize = (12 * dpr) + 'px';
}else{
//否则,等待页面的主要DOM元素加载完毕再去设置body的字体大小
document.addEventListener("DOMContentLoaded",setBodyFontSize);
}
}
setBodyFontSize();
// 核心
// 设置html的文字大小
function setRemUnit(){
// 将html文档宽度划分为10等分,每一等分为一rem,即html的fontsize
var rem = docEl.clientWidth / 10;
docEl.style.fontSize = rem + 'px';
}
setRemUnit();
// 当页面尺寸大小发生变化时,要重新设置rem的大小
window.addEventListener('resize',setRemUnit);
// pageshow 是我们重新加载页面触发的事件
window.addEventListener('pageshow',function(e){
if(e.persisted){
// 返回的是true,说明这个页面是从缓存中去过来的页面,也需要重新计算一下rem的大小
setRemUnit();
}
})
// 下面这块不必了解
// detect 0.5px supports // 有些移动端浏览器不支持0.5像素的写法,下面这个解决方案可以让其支持
if(dpr >= 2){
var fakeBody = document.createElement('body');
var testElement = docunment.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))
示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="flexible.js"></script>
</head>
<body>
</body>
</html>
我的谷歌浏览器物理像素比为1.25
注:
1.javascript中的立即执行函数:
(function () {}() 或者 (function(){} ())
立即执行函数不需要调用就可以执行,第二个小括号可以看做是调用函数。可以给参数,也可以给匿名函数给函数名。
(function sum(a,b){ return a + b;} (1,2))
2.pageshow事件
下面三种情况都会刷新而面都会触发 load 事件
- a 标签的超链接
- F5或者刷新按钮(强制刷新)
- 前进后退接钮
但是火狐中,有个特点,有个“往返缓存”,这个缓存中不仅保存着页面数据,还保存了 DOM和JavaScript 的状态;实际上是将整个页面都保存在了内存里
所以此时后退按钮不能刷新页面。
此时可以使用 pageshow 事件来触发。这个事件在页面显示时触发,无论是否是来自缓存。在重新加载页面中, pageshow 会在 load 事件触发后触发;根据事件对象中的 persisted 判断是否是缓存中的页面触发的 pageshow 事件,注意这个事件给 window 添加。
结语
用这个flexible.js后,你可能需要再装一个cssrem插件,这个插件会自动将你的px转换为rem,提高开发效率,综合来说flexible.js还不错,不用写媒体查询了,且html的fontsize是划分的,一直会随页面大小动态变化,从而实现元素的大小变化。