一、rem 适配基本概念:
二、布局方案:
方案1:
在 index.html 中添加如下代码:
<script>
let html = document.documentElement; window.rem = html.getBoundingClientRect().width / 16 ;
html.style.fontSize = window.rem + 'px';
</script>
这里基于宽 320px 的屏幕分成了 16 份,也就是 1rem = 20px。
目前大多数设计稿都是根据 iphone6 的宽( 375px )走的,建议这里分成 25 份,也就是 1rem = 15px,计算起来方便些。
方案2:
在 index.html 中添加如下代码:
<script>
(function(win, doc) {
var h;
win.addEventListener('resize', function() {
clearTimeout(h);
h = setTimeout(setUnitA, 500);
}, false);
win.addEventListener('pageshow', function(e) {
if (e.persisted) {
clearTimeout(h);
h = setTimeout(setUnitA, 300);
}
}, false);
var setUnitA = function() {
doc.documentElement.style.fontSize = doc.documentElement.clientWidth / 16 + 'px';
};
setUnitA();
})(window, document)
</script>
这段代码监听了窗口调整和页面显示两个事件实现了动态适配的效果。
延展:
1:自执行匿名函数和立即执行的函数表达式区别:
// 这是一个自执行的函数,函数内部执行自身,递归
function foo() { foo(); } // 这是一个自执行的匿名函数,因为没有标示名称
// 必须使用arguments.callee属性来执行自己
var foo = function () { arguments.callee(); }; // 这可能也是一个自执行的匿名函数,仅仅是foo标示名称引用它自身
// 如果你将foo改变成其它的,你将得到一个used-to-self-execute匿名函数
var foo = function () { foo(); }; // 有些人叫这个是自执行的匿名函数(即便它不是),因为它没有调用自身,它只是立即执行而已。
(function () { /* code */ } ()); // 为函数表达式添加一个标示名称,可以方便Debug
// 但一定命名了,这个函数就不再是匿名的了
(function foo() { /* code */ } ()); // 立即调用的函数表达式(IIFE)也可以自执行,不过可能不常用罢了
(function () { arguments.callee(); } ());
(function foo() { foo(); } ()); // 另外,下面的代码在黑莓5里执行会出错,因为在一个命名的函数表达式里,他的名称是undefined
// 呵呵,奇怪
(function foo() { foo(); } ());
注意:arguments.callee在ECMAScript 5 strict mode里被废弃了,所以在这个模式下,其实是不能用的。
参考:http://www.cnblogs.com/TomXu/archive/2011/12/31/2289423.html
我们一直叫的自执行函数,确切的说是自执行匿名函数(Self-executing anonymous function),但此文原作者倡议使用立即调用的函数表达式(Immediately-Invoked Function Expression)这一名称。
2:这里为什么要把windows、document作为参数传进去?
——使全局变量以参数形式变成自执行函数内部的局部变量。
为什么这么做?
——提高程序效率。
为什么能提高效率?
——这得从javascript的机制说起:所谓的scope chain作用域链, 在当前作用域中如果没有该属性(局部变量)则向上一层作用域中寻找,一直到最上层,也就是window。也就是说全局变量和下级作用域都是window的一个属性,向下依此类推。
参考:https://segmentfault.com/q/1010000000311686