性能优化
待完善
- 减少HTTP请求
- 合并资源文件(CSS, JS, 雪碧图)
- 压缩资源文件
- 图片懒加载(借助IntersectionObserver)
- 合理设置HTTP缓存, CDN缓存
- 首屏渲染优化
- 代码分割,路由懒加载
- 骨架屏
- 代码优化
- 不用table (流式布局)
- 不用with, eval
- CSS优化
- CSS3(transform, opacity)硬件加速
- 频繁操作DOM时,可以先用
display: none
使其脱离文 档流再进行DOM操作 - 对于复杂的动画效果,可以使用
position: absolute
使其脱离文档流
- JS优化
- 函数防抖,函数节流
Base64
Base64
的原理就是使用64个可见字符来表示二进制字节序列。
具体来说,对于一个字节序列,我们会把每三个字节作为一组,然后将这24位比特分为四个小组,每个小组前面加上00
。因此原本的24比特变成了32个比特,也就是4个字节,之后再将这些字节分别映射为64个字符。这也是为什么通过Base64
编码后的文本会比原先多三分之一。
基于这个特性,Base64
存在许多用途。最基本的用途是对纯文本进行编码,以达到一种伪加密的手段,比如JWT就使用了Base64
来对数据进行编码。
除此之外,使用Base64
可以把图片资源的二进制内容编码成文本,之后再使用<img src="data:img/gif;base64,base64,xxxxxxxx">
的形式加载,对于小型图片来说我们可以减少HTTP请求数来实现优化的功能。
图片懒加载
常规方法(使用offsetTop - scrollTop 或者 getBoundingClientRect())
<body>
<div class="blank">
// 很长的元素,使图片开始不在视口里
</div>
<div class="image" data-url="C:/Users/Messiah/Pictures/image.png">
// 想要懒加载的图片
</div>
<script type="text/javascript">
let image = document.querySelector('.image')
window.onscroll = throttle(() => {
// 方法一,使用offsetTop - scrollTop
if (image.offsetTop - document.documentElement.scrollTop < document.documentElement.clientHeight)
{
let url = image.dataset.url
image.style.backgroundImage = `url(${url})`
}
// 方法二,使用getBoundingClientRect
if (image.getBoundingClientRect().top < document.documentElement.clientHeight) {
let url = image.dataset.url
image.style.backgroundImage = `url(${url})`
}
}, 200)
// 节流函数
function throttle (fn, time) {
let canRun = true
return function () {
if (!canRun) return false
canRun = false
setTimeout(() => {
fn()
canRun = true
}, time)
}
}
</script>
</body>
offsetParent定义: 一个元素的已定位(position不为static)的父元素, 类似于绝对定位中已经定位的父元素,如果一个元素没有已经定位的父元素,则该元素的offsetParent为body。
此例子中image.offsetTop,image没有已经定位的父元素,则image的offsetParent为body。
如果我们的代码结构如下,
<body>
<div class="outer">
<div class="blank">
</div>
<div class="image">
</div>
</div>
</body>
滚动条在outer上,我们应该给outer加一个样式
.outer {
position: relative;
}
那么,image.offsetParent就是outer,我们就可以继续使用以下代码来判断图片是否进入视口
image.offsetTop - outer.scrollTop < outer.clientHeight
IntersectionObserver
// 使用IntersectionObserver,十分方便
let io = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (!entry.isIntersecting) return
else {
let el = entry.target
el.style.backgroundImage = `url(${el.dataset.url})`
io.unobserve(el)
}
})
})
io.observe(document.querySelector(".image"))
// <div class="image" data-url="https://xxx.com/1.jpg" ></div>
这个API同样能用来实现无限滚动(Infinity Scroll)
雪碧图
合并HTTP请求,使用background-position来选择使用的图片。
setTimeout/setInterval和requestAnimationFrame
setTimeout/setInterval
setTimeout(fn, n)
会在指定的时间n毫秒后,将指定的回调函数fn放进任务队列中,因此并不是n秒后就会执行回调函数。
setTimeout(fn, 0)
即使传参为0ms,最短其实为4 ms。
缺点: 一般显示器刷新频率为60HZ,即16.6ms刷新一次屏幕。setTimeout可能会掉帧。
requestAnimationFrame
function myAnimation() {
// do something
requestAnimationFrame(myAnimation)
}
requestAnimationFrame(myAnimation)
它能保证回调函数在屏幕每一次的刷新间隔中只被执行一次