从渲染的角度出来,前端性能优化可从以下几点入手:
- 懒加载
- 对DOM查询进行缓存
- 频繁DOM操作,合并到一起插入DOM结构
- 节流 防抖
懒加载
如,上滑加载、点击加载 等
<img id="imgDemo" src="preview.png" data-realsrc="real.png">
<script>
var imgDemo = document.querySelector('#imgDemo')
window.onscroll = function() {
var imgTop = imgDemo.getBoundingClientRect().top // 图片顶部距离视口顶部的像素
var height = document.documentElement.clientHeight // 文档高度
if (imgTop <= height) {
imgDemo.src = imgDemo.getAttribute('data-realsrc')
}
}
</script>
对DOM查询进行缓存
声明一个变量,缓存DOM查询结果
// 不缓存DOM查询结果
for (let i = 0; i < document.querySelectorAll('li').length; i++) {
//每次循环都会计算length,频繁进行DOM查询
}
// 缓存DOM查询结果
const lis = document.querySelectorAll('li')
const length = lis.length
for (let i = 0; i < length; i++) {
// 缓存 length,只进行一次DOM查询
}
频繁DOM操作,合并到一起插入DOM结构
document.createDocumentFragment() 创建文档片段
(减少回流和重绘)
var ul = document.querySelectorAll('ul')
var frag = document.createDocumentFragment() // 创建文档片段,此时还没有插入DOM树中
for (let i = 0; i < 6; i++) {
var li = document.createElement('li')
li.innerText = `li${i}`
frag.appendChild(li) // 在frag中插入节点不会影响DOM
}
ul.appendChild(frag) // 一次性插入DOM
节流 防抖
节流:一段时间内执行一次之后,就不执行第二次(类似游戏技能有冷却时间)
function throttle(fn, delay){
let canUse = true
return function(){
if(canUse){
fn.apply(this, arguments)
canUse = false
setTimeout(()=>canUse = true, delay)
}
}
}
const throttled = throttle(()=>console.log('hi'),3000)
throttled()
防抖:一段时间内触发多次,只执行最后一次
function debounce(fn, delay){
let timerId = null
return function(){
if(timerId){
clearTimeout(timerId)
}
timerId = setTimeout(()=>{
fn.apply(this, arguments)
timeID = null
},delay)
}
}
const debounced = debounce(()=>console.log('hi'),3000)
debounced()