09、移动性能优化

zhanghao 2020-04-21

CSS、js文件优化

内联css、js

优点:减少HTTP请求

缺点:

1、代码难以复用

2、使html文件变大,加载事件变长

3、写在html中不利于后期维护。(工程化手段可以解决。源码到可以上线的代码)

外联css、js

优点:

1、很好地复用代码。(有效利用浏览器静态资源缓存)

2、代码分离,利于后期维护。

缺点:增加HTTP请求

综合解决方案

首屏代码用内联,其他可以用外联。

文件先后位置

css文件放在head里面,越早加载越好。

js文件,没有dom操作的,如屏幕适配,可放head里面。

js文件,有dom操作的,放在body结束前。

图片优化

HTTP请求大

//如图片大,可以这样解决:

1、图片压缩处理。使用更高压缩比的图片格式,如webp

2、尽量少用图片。用css画图 或者 用图标字体代替图片。

HTTP请求多

//如图片多,可以这样解决:

1、合理使用base64内嵌图片。

2、合并图片,如雪碧图。(用时可background-position)

其他优化

1、避免重复加载css、js文件。

2、上线代码删除注释、空格、换行等。(上线可使用  代码压缩插件 / 在线压缩工具 )

3、使用浏览器缓存。(后端解决)

4、避免多重嵌套。

5、空链接,如 href=" " 或 src=" " 等等,里面最好写上#。避免再发送一次http请求。

6、避免慢标签,如 table 或 iframe等。浏览器会把里面内容全读完后再一次渲染到页面。(读取过程中,网页上有一块空白,读完后一下子出现)

7、主要内容写在前面,次要内容写在后面。

CSS优化

选择器优化

 第一种

//dom
<div id="dd" class="dd"></div>

//css
div#dd.dd{} //避免这种情况,虽然更加精确,但是浏览器查找解析慢。
.dd{}  //不冲突的情况这样即可

第二种

//dom
<div class="aa">
    <div class="bb">
        <div class="cc"></div>
    </div>
</div>

//css
.aa .bb .cc{} //避免这种情况,浏览器会从右到左一个个解析,直到所有条件匹配。而且后面不容易修改,因为这里权重比较高了。
.cc{}  //不冲突的情况这样即可

第三种

//dom
...

//css
*{    //在项目开发阶段可以用一下,上线代码就尽量不用,因为它会找页面上所有的元素,进行清空内外边距。比较浪费资源
    padding:0;
    margin:0
} 
div,dd,dt{        //可以这样。需要清空哪些元素,就清空
    padding:0;
    margin:0    
}

 属性优化

 第一种

.cc{
    width:100px;
    height:100px;
}
.dd{
    width:100px;
    height:100px;
}

//避免写重复的属性,可以直接这样,把重复的写一块

.cc,.dd{
    width:100px;
    height:100px;
}

第二种

.aa{
    margin-top:10px;
    margin-right:10px;
    margin-bottom:10px;
    margin-left:10px;
}

//属性能写一块就写一块,如:
.aa{
    margin:10px; //四边都为10px
    //margin:10px 10px; //上下 左右 
    //margin:10px 10px 10px;    //上 左右 下
    //margin:10px 10px 10px 10px;     //上右下左
}

 其他优化

1、合理开启gup加速

2、移动端推荐flex,不要滥用float。(float性能消耗比flex多)

3、css中尽量少用@import url(‘base.css‘),因为在加载css中遇到会再发送一次加载base.css的请求。

DOM优化 

//dom操作非常消耗性能 

三个原则

1、加快单次dom操作。

2、尽量减少dom操作的次数。

3、能用id尽量用id,不要为了使用id而使用id

第一种优化

//dom
<div id="aa">
    <div id="bb">123</div>
</div>
//平常获取aa、bb
var aa = document.getElementById(‘aa‘);
var bb = document.getElementById(‘bb‘);

//优化:在获取bb的时候完全不用在document里面找,可以从aa里面找
var bb = aa.getElenentById(‘bb‘);

 第二种

for(var i=0; i<40; i++){
    aa.innerHTML += i;
}
//上面操作dom的次数就达到了40次,非常消耗资源。可以这样
for(var i=0; i<40; i++){
    html += i;            //字符串操作消耗资源非常低
}
aa.innerHTML = html;    //这样操作一次dom就实现了

第三种。dom操作中说过

for(var i=0; i<30; i++){
    var sp = document.createElement(‘span‘);//创建30次
    sp.innerText = i;
    aa.appendChild(sp);    //渲染30次
}

//这样就执行了30次dom操作了,损耗资源。可以这样

var fragment = document.createDocumentFragment();    //创建虚拟节点对象
var sp = document.createElement(‘span‘);    //创建一次span

for(var i=0; i<30; i++){
    var span = sp.cloneNode(true); //true表示拷贝sp本身+数据;false表示拷贝sp本身。cloneNode比createElement性能更好
    span.innerText = i;
    fragment.appendChild(span);    //将东西填充到虚拟节点对象里面,虽说填充但是完全不会进行页面渲染    
}
aa.appendChild(fragment);    //这里只做了一次dom操作

第四种

for(var a=0; a<pp.length; a++)
//这样的话每一次都用dom获取pp的长度,可以适当将pp.length保存起来。如:

for(var a=0,b=pp.length; a<b; a++)
//这样性能更好

 浏览器渲染机制

渲染 = 重排 + 重绘

重排 = 计算网页中各个元素的位置关系
重绘 = 获取元素的样式,将样式绘制到浏览器中

每一次dom的操作都会引发重排/重绘。
引发重排必定引发重绘,引发重绘只是将该元素样式重新绘制一遍

如:

aa.style.fontSize = ‘20px‘;
aa.style.color = ‘red‘;
aa.style.backgroundColor = ‘green‘;

//修改一个以上的样式,建议通过切换class名来进行,切换一次class名就重绘一次
//若像上面直接改变样式可能会引发多次重绘(有些老式浏览器可能得重绘3次)

事件优化

 //善用 事件委托 与 事件节流

事件委托

//好处,不用循环遍历ul里面的每一项。js事件中有说过

<ul id="ul">
<li class="qq"> one </li>
<li class="qq"> two </li>
<li class="qq"> three </li>
</ul>

var ul = document.getElementById("ul");
ul.addEventListener("click",function(event){

if(event.target.className == "qq")  alert("触发了li元素");

},false);

 事件节流

//scroll、resize、mousemove、touchmove等等事件每一次都多次触发。只需要触发一次的话可以

var timer = null;
window.addEventListener(‘scroll‘,function(){
    clearTimeout(timer);
    timer = setTimeout(function(){
        console.log("这样就执行一次了");
    },100)
},false)

按需加载(懒加载)

1、所有图片src属性路径,都设置成转圈圈gif图。

2、真正需要显示的图片放到一个自定义的属性里,如data-src

3、在需要 按需加载的图片标签,加一个class,如 lazyload-img。这样就可以获取到所有还没加载出来的图片 

4、获取所有按需加载的图片集合,并转为数组

var jihe = document.querySelectorAll(‘.lazyload-img‘);     //需要使用数组的方法,所以需要转换成数组

var imgArr = Array.prototype.slice.call(jihe);    //用这个方法就可以,将类数组转换为数组

5、当页面刚加载进来时,执行一下懒加载,将可视区范围内的图片加载出来

lazyLoadImgs();  //函数稍后定义

6、集合中的图片出现在了可视区范围内,就执行按需加载

var timer = null;
window.addEventListener(‘scroll‘,function(){
    clearTimout (timer);
    timer = setTimeout(function(){
        lazyLoadImg();
    },100)
},false)

7、lazyLoadImgs函数

function lazyLoadImgs(){
    //先遍历集合里面的图片
    for(var i=0; i<imgArr.length; i++){
    
        if(isInvisibleArea(imgArr[i])){        //判断当前第i个图片是否在可视区范围内

            imgArr[i].src = imgArr[i].getAttribute(‘data-src‘);     //若在可视区范围内就将src的转圈图标类名,换成真正的类名

            imgArr.splice(i,1);  //将当前显示出来图片,从集合里面移除

            i--;    // [0,1,2,3] 当前下标为0的元素删除,末尾循环会i++,下一次再进入循环i下标1,但是下标为1的的元素变成2了,元素1还没出现过,就会漏掉一个。必须进行i--

        }  
    }
}

8、isInvisibleArea函数

function isInvisibleArea(el){    //判断某元素是否在可视区范围内
    var rect = el.getBoundingClientRect(); 
    //这样top值小于屏幕宽度,元素就在可视区内;bottom值等于0元素就在可视区外。
    return rect.bottom > 0 && rect.top < window.innerHeight; //只要条件成立就返回真
}

09、移动性能优化

按需加载其他文件

//dom中
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div id="a">还没加载到</div>

//css部分
width:300px;
height:300px;
background-color:red;
font-size:30px;
color:white;

//js部分

/*滚动条每动一次就判断一次,该元素是否在可视区内*/
var timer = null;
window.addEventListener(‘scroll‘,jieliu,false)

function jieliu(){
    clearTimout (timer);
    timer = setTimeout(function(){
        panduan(a);    //判断函数
    },100)
}

function panduan(el){    //判断某元素是否在可视区范围内
    var rect = el.getBoundingClientRect(); 

    var jieguo = rect.bottom > 0 && rect.top < window.innerHeight; //只要条件成立就返回真

    if(jieguo){     //如果在可视区内就,加载外部js
        setTimeout(function () {    //延时是为了模仿慢速网络
            var script = document.createElement(‘script‘);
            script.src = ‘js/loadProduct.js‘;

             document.body.appendChild(script); //将引进来的js加载到body中

            window.removeEventListener(‘scroll‘, jieliu, false); //执行完成后就可以解绑scroll
        }, 3000);

       
    }
}

//外部js
var a = document.getElementById(‘a‘);
a.innerText = "加载到了,真好";

预加载

当浏览器检测到当前空闲的时候,会把可能需要的资源下载下来。如漫画

var img = new Image();
img.src = ‘./22.jpg‘;    //将预加载实际路径赋给img的src属性即可

相关推荐

ganyouxianjava / 0评论 2012-05-31