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
var timer = null;
window.addEventListener('scroll',1)"> () {
console.log('scroll');不节流
100ms内有重复执行,则取消前面的执行
clearTimeout(timer);
timer = setTimeout( () {
console.log('scroll');节流
},100);
....
},1)">false);
<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>
( () {
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 举报,一经查实,本站将立刻删除。