某厂面试题:移动端适配为何这样不行?

参加某公司面试,当面试官问到移动端如何适配的时候,我给出的方案是:
在head里面插入js代码

//假设设计稿是640的宽度
var width = (window.innerWidth)*100/640;
document.write("<style type='text/css'>html{font-size:"+width+"px;}</style>")

然后网站用rem布局.
不知道此方法的缺陷是在哪里,望高人指点...

阅读 9.6k
12 个回答

我前不久写的一篇文章写了如何用rem做页面适配,建议你去读一读。

rem : web app适配的秘密武器

没有实战经验的同学就非常难以理解为什么除以640不行,非要除以320才可以。

我文章中的例子设计稿是750宽度,除以2就是375.

设计师在出设计图的时候,之所以会选择@x2的尺寸,只不过是因为320的设计图确实太小了。所以我们在计算尺寸的时候,肯定是要除回来的。所以这个小地方就能够看出来你是否有真的动手实践过。只要动手实践过就能够体会出来问题所在了。所以,640一出,你已被判刑!!

另外有几个细节的地方需要注意

  1. 实际开发中,几乎不会用到document.write这种方法的,就算是你要修改元素的样式,也不是这样写的

  2. rem并不是全能适配王,在某些落后Android机型上是不支持的,因此要慎用。不过大多数手机都没有问题。

  3. 移动端适配几乎不会涉及到@media的媒体查询,这并不是一个高性能的选择,只有一个页面从pc端高分屏适配到移动端才会用到这个,大多数情况下,用到了@media,那么单位就只能用px或者em而不能使用rem。

若适配要求不高的话,直接用css来做就好,@media screen and()这类来做; 要求高的用js,可以使用rem,方法一:document.documentElement.style.fontSize = document.documentElement.clientWidth / 6.4 + 'px';方法二:使用手机淘宝方法flexible

这样写只在载入时执行一次,特别是当设备横屏、改变窗口大小时 并不能完整的适配。
需要使用JS动态的改变html的font-size值:

//自适应REM设置
!function(){
    var isChange= false, oldScreenWidth= 375, oldRem= 50;   // 默认iPhone6为基准[屏款375,默认根字体大小50px]
    var html= document.getElementsByTagName('html')[0];
    var getStyle = function (element,attr) {
        if(typeof window.getComputedStyle!='undefined'){
            return parseFloat(window.getComputedStyle(element,null)[attr]);
        }else if(element.currentStyle){
            return parseFloat(element.currentStyle[attr]);
        }
    };
    function initRem(){
        console.log(document.body.clientWidth, getStyle(html, 'font-size'));
        html.style.fontSize= document.body.clientWidth*oldRem/oldScreenWidth+'px';
        oldScreenWidth= document.body.clientWidth;
        oldRem= getStyle(html, 'font-size');
        isChange= false;
    }
    document.addEventListener('DOMContentLoaded', function(){
        initRem();
    });
    window.addEventListener('resize', function(){
        if(!isChange){
            isChange= true;
            setTimeout(initRem, 700);
        }
    })
}();

至于基准单位什么的都可以更具自己需要设置,比如上面的:1rem= 50px。

使用rem布局的优点是可以在所有设备上保证与设计稿一样的布局效果和显示,缺点是当在大屏设备上时布局的不够有效(屏幕宽但是显示的内容少,体验不好。比如ipad)、另外换算也比较复杂,开发周期相对于要慢一些。

网易是使用你这种解决方案的,你去的某厂不比网易高就不必改了

我是这样认为的。

  1. 先抛出viewport概念

  2. 正对不同终端,应该有不同的css效果

@media screen and (max-width: 300px) {
    body {
        background-color:lightblue;
    }
}
  1. 最后再强调js大法

我反对
不同设备应该准确投送样式

这个看下。

function setFont(d, c) {
    var b = {},
        a = document,
        f;
    b.widthProportion = function() {
        var e = (a.body && a.body.clientWidth || a.getElementsByTagName("html")[0].offsetWidth || window.innerWidth) / d;
        // console.log(e);
        return e
    };
    b.changePage = function() {
        var f = b.widthProportion() * c,
            obj = a.getElementsByTagName("html")[0];
            console.log("f: " + f);
        obj.setAttribute("style", "font-size:" + f + "px !important");
        var style = null;
        if (window.getComputedStyle) {
            style = window.getComputedStyle(obj, null);
            font = style.fontSize;
            console.log("font: " + font);
            font = Number(font.replace("px", ""));
            if (font > f) {
                var per = font / f;
                console.log(per);
                obj.setAttribute("style", "font-size:" + f / per + "px !important");
            }
        }
    };
    b.changePage();
    addEventListener("resize", b.changePage, false);
}
setFont(750, 100);

改变htmlfont-size然后使用rem来布局是很好的方法,只要注意把功能写全,你去的那家公司凭啥说这种方法不好呢,有什么理由吗?

一般移动端的适配 移动端和桌面端的布局是不一样的 这是我们常说的响应式布局 如果只是像你这样写,这是保证了无论在什么屏幕尺寸下都按照某一设计的比例,位置显示, 不是移动端适配,这种解决的是不同移动端设备尺寸下如何按照某一移动端设计稿按设计里面的比例“完美“显示出来

这个问题答案比较多,但是最近我遇到的就是 js 配合 rem
1.和UI定好设计稿的标准尺寸。一般是750px iphone6的大小。
2.viewport:

<meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, width=device-width, user-scalable=no">

3.使用less或者sass根据px去计算rem的值。因为你的设计稿是以PX为单位,不可能你每个都去手算吧。写函数。
4.然后在js中抓取屏幕宽度设置好1rem = 屏幕宽度/10-20 font-size 。html根元素 font-size = 1rem。设置好当屏幕改变或者启动自动再计算一下font-size 的值 。
5.完成 现在css中就按照这个算法就行了。

新手上路,请多包涵
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏