移动端性能优化JavaScript性能优化

JavaScript性能优化

 

DOM操作优化

查找DOM元素能用id就用id,是最高效的查找方法(还得看具体环境)

document.getElementById('slider')

 

从document开始查找子元素效率不高,建议从具体父元素开始查找

减少元素查找的层级

            var sliderItemContainer = document.querySelector('.slider-item-container');//从DOM开始查找
            var sliderItemContainer = sliderEl.querySelector('.slider-item-container');从具体元素开始查找

 

DOM操作完使用变量缓存,否则需要多次操作DOM就得多次获取

             合理缓存DOM对象
            var sliderItemContainer = sliderEl.querySelector('.slider-item-container'),sliderItem = sliderItemContainer.querySelectorAll('.slider-item'
            for (var i = 0,num = sliderItem.length; i < num; i++) {
                 indicatorContainer.innerHTML += '<span class="slid
             }
  

推荐

             减少操作DOM的次数
            var html="";
            ) {
                html += '<span class="slider-indicator"></span>';
                }

                indicatorContainer.innerHTML=html ;
            }

也可以使用文档碎片,因为还没有被渲染呈现,因此循环中不涉及DOM渲染 

在循环外只创建一遍文档碎片节点,在循环内克隆节点即可,传入true可以带内容一起拷贝

           var indicatorItemFragment = document.createDocumentFragment();创建文档片段
           var spanEl = document.createElement('span');

            ) {
                var indicatorItem = spanEl.cloneNode(true);
                indicatorItem.className = 'slider-indicator';
                indicatorItemFragment.appendChild(indicatorItem);
            }

 

循环的长度也用变量保存下来,只在最初执行一次

不推荐

var i = 0; i < sliderItem.length; i++)

推荐


                 不要直接修改style,通过添加class修改
                if (i === activeIndex) {
                    indicatorItem.style.backgroundColor = '#007aff';
                    indicatorItem.style.opacity = 1;
                     重排 重绘
                }

推荐

                 activeIndex) {
                    indicatorItem.className += ' slider-indicator-active';
                }

 

事件的优化:

避免事件多次绑定,而且如果改变节点时还需要增加或解除绑定

避免遍历节点,给每个元素都绑定事件

可以使用事件代理或者事件委托,给它们的父元素绑定一次事件即可(事件冒泡原理)

不推荐

        var sliderEl = document.getElementById('slider'= sliderIndicatorContainer.querySelectorAll('.slider-indicator');

         事件绑定
        ) {
            sliderIndicators[i].addEventListener('click',function () {
                console.log('click');
            },false);
        }

         动态插入一个新节点
        var sliderIndicator = document.createElement('span');
        sliderIndicator.className = 'slider-indicator';
        sliderIndicatorContainer.appendChild(sliderIndicator);
        sliderIndicator.addEventListener('click',1)"> () {
            console.log('click');
        },1)">false);

推荐

         使用事件代理,避免直接事件绑定
         jQuery/Zepto
        $(sliderIndicatorContainer).on('click','.slider-indicator',1)"> () {});

        原生js
        sliderIndicatorContainer.addEventListener('click',1)"> (ev) {
             console.log(ev.target);//ev.target获取到当前点击的元素
            if (ev.target && /(^|\s)slider\-indicator($|\s)/.test(ev.target.className)) {
                正则判断当前点击的元素的className
                console.log('click');
            }
        },1)">false);

 

针对执行非常频繁的事件,使用事件节流来稀释

比如 scroll resize mousemove touchmove等事件

         事件节流
         scroll resize mousemove touchmove
        var timer = null;
        window.addEventListener('scroll',1)"> () {
            console.log('scroll');不节流

            100ms内有重复执行,则取消前面的执行
            clearTimeout(timer);
            timer = setTimeout( () {
                console.log('scroll');节流
            },100);
             ....
        },1)">false);

 

 

资源按需加载(懒加载,延迟加载)

将img的src属性可以先放在data-src(自定义属性)里,默认src里放一个统一的loading小图标

给需要按需加载的图片添加一个统一的类

<img src="img/loading.gif" data-src="img/recommend/1.jpg" alt="recommend" class="recommend-img lazyload-img">

获取到所有需要按需加载的图片节点,存入数组中

        var lazyLoadClass = '.lazyload-img';
        Array.prototype.slice.call()类数组转数组
        var imgArr = Array.prototype.slice.call(document.querySelectorAll(lazyLoadClass));获取到所有需要按需加载的节点列表,转数组

        console.log(imgArr);

 

 初始化时和每次滚动时,都执行按需加载函数

        lazyLoadImgs();初始化时执行图片加载

        每次滚动时也执行图片加载
         () {
            clearTimeout(timer);
            timer = setTimeout( () {
                lazyLoadImgs();
            },100false);

判断元素是否在可视区内

         是否在页面可视区内
         isInVisibleArea(el) {
            var rect = el.getBoundingClientRect();
             rect.top 可视区顶部到物体顶部
             rect.bottom  可视区底部到物体底部
             rect.right 可视区右边到物体右边
             rect.left 可视区左边到物体左边

            return rect.bottom > 0 && rect.top < window.innerHeight && rect.right > 0 && rect.left < window.innerWidth;
        }

按需加载函数

         lazyLoadImgs() {
            var i = 0; i < imgArr.length; i++) {
                判断是否在可视区范围
                if (isInVisibleArea(imgArr[i])) {
                    imgArr[i].src = imgArr[i].getAttribute('data-src');用data-src属性填充到src属性中
                    imgArr.splice(i,1);数组中剔除已经加载的图片
                    i--;数组长度减少
                }
            }
        }

完整代码:

<!DOCTYPE html>
html lang="zh-CN"head>
    meta charset="UTF-8"name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no"title>4.3 资源按需加载和预加载</link rel="stylesheet" href="css/base.css"="css/icons.css"="css/index.css"script ="js/flexible.js"></scriptbodyheader class="header-container">
        div ="navbar">
            ="navbar-left">
                i ="iconfont icon-scan"idiv="navbar-center"="searchBox">
                    ="searchBox-prepend">
                        ="iconfont icon-search"input type="text" placeholder="开学季有礼,好货5折起"="searchBox-input"="searchBox-append"="iconfont icon-close"="navbar-right"="iconfont icon-msg"header>

    ="main-container"="slider-container"="img/slider/1.jpg"="slider">

        nav ="nav-container"ul ="nav"li ="nav-item"a href="###"="nav-link"="img/nav/1.png"="nav"="nav-img"span ="nav-text">团购spanali="img/nav/2.png">一元购="img/nav/3.png">优惠券="img/nav/4.png">教育="img/nav/5.png">旅行="img/nav/6.png">在线订餐="img/nav/7.png">庆典="img/nav/8.png">秒杀="img/nav/9.png">拍卖="img/nav/10.png">服务ulnav="recommend-container"="recommend"="recommend-item"="recommend-link"p ="recommend-pic">
                            p="recommend-name">欧派整体橱柜定制简约现代="recommend-origPrice"del>¥2000.00="recommend-info"="recommend-price">¥strong ="recommend-price-num">1000strong="recommend-count">985件已售="img/recommend/2.jpg">创维55吋4K超高清HDR>¥2999.00>2299>63件已售="img/recommend/3.jpg">【到手259元】苏泊尔 5L电压力锅>¥799.00>299>1908件已售="img/recommend/4.jpg">三只松鼠坚果礼包>¥125.00>108>9532件已售="img/recommend/5.jpg">蓝月亮洗衣液12斤>¥133.40>89.9>5399件已售="img/recommend/6.jpg">福临门葵花玉米油>¥109.90>6294件已售="img/recommend/7.jpg">TP-LINK 全千兆端口双频无线路由器>¥179.00>169>4255件已售="img/recommend/8.jpg">【前1800名再减50】家用高压洗车机>¥790.00>268>1599件已售="img/recommend/9.jpg">德国鲁茜rusch迷你婴儿辅食机 宝宝>¥898.00>159>881件已售="img/recommend/10.jpg">西域之尚红枣500g*5袋>¥89.00>29.9>15049件已售<!-- 资源按需加载 -->
        id="product" style="height: 500px; background-color: red; text-align: center; line-height: 500px; font-size: 2.5rem; color: #fff;"=""="tabbar-container"="tabbar"="tabbar-item tabbar-item-active"="tabbar-link"="iconfont icon-home">首页="tabbar-item"="iconfont icon-category">分类页="iconfont icon-cart">购物车="iconfont icon-personal">个人中心>
        // 1. 图片的按需加载
        var lazyLoadClass = '.lazyload-img;
        Array.prototype.slice.call()类数组转数组
         imgArr = Array.prototype.slice.call(document.querySelectorAll(lazyLoadClass));获取到所有需要按需加载的节点列表,转数组

        console.log(imgArr);

        lazyLoadImgs();初始化时执行图片加载

        每次滚动时也执行图片加载
         timer null;
        window.addEventListener(scroll,function () {
            clearTimeout(timer);
            timer  setTimeout(100false);

         lazyLoadImgs() {
            for ( i 0; i < imgArr.length; i++) {
                判断是否在可视区范围
                if (isInVisibleArea(imgArr[i])) {
                    imgArr[i].src  imgArr[i].getAttribute(data-src);用data-src属性填充到src属性中
                    imgArr.splice(i,1)">1数组中剔除已经加载的图片
                    i--;数组长度减少
                }
            }
        }

         是否在页面可视区内
         isInVisibleArea(el) {
             rect  el.getBoundingClientRect();
             rect.top 可视区顶部到物体顶部
             rect.bottom  可视区底部到物体底部
             rect.right 可视区右边到物体右边
             rect.left 可视区左边到物体左边

            return rect.bottom > 0 && rect.top  window.innerHeight  rect.right  rect.left  window.innerWidth;
        }


    html>

 

 

 

 

其他资源的按需加载

js/loadProduct.js
( () {
    var product = document.getElementById('product');

    product.innerHTML = '我是按需加载的';
})();

html中代码添加:

         2. 其他内容的按需加载
        loadProduct();
        window.addEventListener('scroll',loadProduct,1)"> loadProduct() {
            if (isInVisibleArea(document.getElementById('product'))) {
                var script = document.createElement('script');
                 script.src = 'js/loadProduct.js';
                使用setTimeout是为了模拟网络延迟,上线时不需要延迟
                setTimeout( () {
                    script.src = 'js/loadProduct.js';
                },1000);
                document.body.appendChild(script);载入loadProduct.js

                window.removeEventListener('scroll',1)">);
            }
        }

 

 

 

预加载(空闲的时候加载,之后用到的时候已经加载完了)

常用于浏览漫画的时候

         3. 图片预加载
        var img = new Image();
        img.src = 'img/recommend/5.jpg';

 

 (还没滚动就已经预加载了)

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


HTML5和CSS3实现3D展示商品信息的代码
利用HTML5中的Canvas绘制笑脸的代码
Html5剪切板功能的实现
如何通过HTML5触摸事件实现移动端简易进度条
Html5移动端获奖无缝滚动动画实现
关于HTML5和CSS3实现机器猫的代码
HTML5使用DOM进行自定义控制
使用HTML5 Canvas绘制阴影效果的方法
使用PHP和HTML5 FormData实现无刷新文件上传
如何解决HTML5 虚拟键盘出现挡住输入框的问题
HTML5中div和section以及article的区别分析
html5和CSS 实现禁止IOS长按复制粘贴功能
html5 touch事件实现触屏页面上下滑动
canvas 模拟实现电子彩票刮刮乐的代码
HTML5 Plus 实现手机APP拍照或相册选择图片上传的功能
Android自定义环形LoadingView效果
HTML5 canvas绘制五角星的方法
html5使用html2canvas实现浏览器截图
使用Canvas处理图片的方法介绍
利用Canvas模仿百度贴吧客户端loading小球的方法