從渲染的角度出來(lái),前端性能優(yōu)化可從以下幾點(diǎn)入手:
- 懶加載
- 對(duì)DOM查詢進(jìn)行緩存
- 頻繁DOM操作,合并到一起插入DOM結(jié)構(gòu)
- 節(jié)流 防抖
懶加載
如,上滑加載、點(diǎn)擊加載 等
<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>
對(duì)DOM查詢進(jìn)行緩存
聲明一個(gè)變量,緩存DOM查詢結(jié)果
// 不緩存DOM查詢結(jié)果
for (let i = 0; i < document.querySelectorAll('li').length; i++) {
//每次循環(huán)都會(huì)計(jì)算length,頻繁進(jìn)行DOM查詢
}
// 緩存DOM查詢結(jié)果
const lis = document.querySelectorAll('li')
const length = lis.length
for (let i = 0; i < length; i++) {
// 緩存 length,只進(jìn)行一次DOM查詢
}
頻繁DOM操作,合并到一起插入DOM結(jié)構(gòu)
document.createDocumentFragment() 創(chuàng)建文檔片段
(減少回流和重繪)
var ul = document.querySelectorAll('ul')
var frag = document.createDocumentFragment() // 創(chuàng)建文檔片段,此時(shí)還沒(méi)有插入DOM樹(shù)中
for (let i = 0; i < 6; i++) {
var li = document.createElement('li')
li.innerText = `li${i}`
frag.appendChild(li) // 在frag中插入節(jié)點(diǎn)不會(huì)影響DOM
}
ul.appendChild(frag) // 一次性插入DOM
節(jié)流 防抖
節(jié)流:一段時(shí)間內(nèi)執(zhí)行一次之后,就不執(zhí)行第二次(類似游戲技能有冷卻時(shí)間)
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()
防抖:一段時(shí)間內(nèi)觸發(fā)多次,只執(zhí)行最后一次
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()