目录
1. 回流重绘
重绘不⼀定重排,重排必定重绘
布局发生了改变就会触发重排(回流),样式发生了改变就会触发重绘
1.1 回流与重绘的概念及触发条件
重绘:一个元素的 样式/ 几何属性发生改变(例如背景色、文字颜色),但是没有改变布局属性(元素外观重新展示)
重排(回流):元素布局位置发生变化,倒回去重新渲染
display:none会触发重排,visibility:hidden会触发重绘
回流触发条件
- 页面首次渲染
- 浏览器窗口尺寸改变——resize事件发生时
- 元素内容/尺寸/位置发生变化
- 添加或者删除可见的DOM元素
1.2 避免回流与重绘
- 浏览器自身优化(渲染队列)
- 批量修改DOM
- 不要使用Table布局
- position属性使用absolute或者fixed
- visibility:hidden替换display:none
- 使用CSS3硬件加速
- 避免设置多层内联样式
回答总结!!!
重排和重绘是浏览器关键渲染路径上的两个节点, 浏览器的关键渲染路径就是 DOM 和 CSSOM 生成渲染树,然后根据渲染树通过一个布局(也叫 layout)步骤来确定页面上所有内容的大小和位置,确定布局后,将像素绘制 (也叫 Paint)到屏幕上。
其中重排就是当元素的位置发生变动的时候,浏览器重新执行布局这个步骤,来重新确定页面上内容的大小和位置,确定完之后就会进行重新绘制到屏幕上,所以重排一定会导致重绘。
如果元素位置没有发生变动,仅仅只是样式发生变动,这个时候浏览器重新渲染的时候会跳过布局步骤,直接进入绘制步骤,这就是重绘,所以重绘不一定会导致重排。
2. 防抖和节流
防抖和节流都是在高频事件中防止函数被多次调用,是一种性能优化的方案。
防抖是某一段时间只执行一次,而函数节流是间隔时间执行。
辅助理解: 节流防抖就好比乘电梯,比如delay是10秒,防抖就是电梯每进来一个人就要等10秒再运行,而节流就是电梯保证每10秒可以运行一次。
2.1 防抖(debouce)
原理:
通过setTimeout的方式,在一定事件间隔内(n秒之后),将多次触发变成一次触发。在事件触发n秒后再执行回调,如果在n秒内再次触发,则重新计算时间。
主要应用场景:
- 搜索框输入查询:防止用户不断输入过程中,不断请求资源,等用户停止输入的时候,再调用,节约请求资源
- 按钮提交事件/表单验证:比如点赞,表单提交,防止多次提交
- 浏览器窗口缩放,resize事件:不断调整浏览器窗口大小会不断的触发这个事件,用防抖让其只触发一次
- scroll事件滚动触发
2.2 节流(throttle)
原理:
规定在一个单位时间内,只能触发一次函数。 如果这个单位时间内触发多次函数,只有一次生效。
主要应用场景:
- 监听滚动scroll事件,是否滑到底部自动加载更多
- 鼠标不断点击触发,mousedown(单位时间内只触发一次)
- 计算鼠标移动的距离(mousemove)
- DOM元素的拖拽功能实现(mousemove)
- 搜索联想(keyup)
2.3 实现节流函数和防抖函数
函数防抖
function debounce(fn, wait) {
var timer = null;
return function() {
var context = this,
args = [...arguments];
// 如果此时存在定时器的话,则取消之前的定时器重新记时
if (timer) {
clearTimeout(timer);
timer = null;
}
// 设置定时器,使事件间隔指定事件后执行
timer = setTimeout(() => {
fn.apply(context, args);
}, wait);
};
}
函数节流
// 时间戳版
function throttle(fn, delay) {
var preTime = Date.now();
return function() {
var context = this,
args = [...arguments],
nowTime = Date.now();
// 如果两次时间间隔超过了指定时间,则执行函数。
if (nowTime - preTime >= delay) {
preTime = Date.now();
return fn.apply(context, args);
}
};
}
// 定时器版
function throttle (fun, wait){
let timeout = null
return function(){
let context = this
let args = [...arguments]
if(!timeout){
timeout = setTimeout(() => {
fun.apply(context, args)
timeout = null
}, wait)
}
}
}
3. 懒加载
懒加载也叫延迟加载,指的是在长网页中延迟加载图片的时机,当用户需要访问时,再去加载。这样可以提高网站的首屏加载速度,提升用户的体验,并且可以减少服务器的压力。
实现原理
图片的加载是由src引起的,当对src赋值时,浏览器就会请求图片资源。
根据这个原理,我们使用HTML5 的data-xxx属性来储存图片的路径,在需要加载图片的时候,将data-xxx中图片的路径赋值给src,这样就实现了图片的按需加载,即懒加载。
注意:data-xxx 中的xxx可以自定义,这里我们使用data-src来定义
4. CDN
CDN(内容分发网络)是指一种通过互联网互相连接的电脑网络系统,利用最靠近每位用户的服务器,更快、更可靠地将音乐、图片、视频、应用程序及其他文件发送给用户,来提供高性能、可扩展性及低成本的网络内容传递给用户。
典型的CDN系统由下面三个部分组成:分发服务系统、负载均衡系统、运营管理系统
作用:CDN一般会用来托管Web资源(文本、图片和脚本等),可供下载的资源(媒体文件、软件、文档等),应用程序(门户网站等),使用CDN来加速这些资源的访问。
5. 项目中图片优化
- 不用图片。修饰类图片可以用 CSS 代替
- 小图使用 base64 格式
- 将多个图标文件整合到一张图片中(雪碧图,精灵图)
- 对于移动端来说,没有必要去加载原图。一般图片都用 CDN 加载
- 选择正确的图片格式:
对于能够显示 WebP 格式的浏览器尽量使用 WebP 格式;
小图使用 PNG,图标这类图片,使用 SVG 代替;
照片使用 JPEG;
6. Webpack优化
6.1 如何⽤webpack来优化前端性能
⽤webpack优化前端性能是指优化webpack的输出结果,让打包的最终结果在浏览器运⾏快速⾼效。
- 压缩代码:删除多余的代码、注释、简化代码的写法等等⽅式。
- 利⽤CDN加速: 在构建过程中,将引⽤的静态资源路径修改为CDN上对应的路径。
- Tree Shaking: 将代码中永远不会⾛到的⽚段删除掉。
- Code Splitting: 将代码按路由维度或者组件分块(chunk)
- 提取公共第三⽅库
6.2 如何提高webpack的构建速度
- 多⼊⼝情况下,使⽤ CommonsChunkPlugin 来提取公共代码
- 通过 externals 配置来提取常⽤库
- 利⽤ DllPlugin 和 DllReferencePlugin 预编译资源模块
- 使⽤ Happypack 实现多线程加速编译
- 使⽤ webpack-uglify-parallel 来提升 uglifyPlugin 的压缩速度。
- 使⽤ Tree-shaking 和 Scope Hoisting 来剔除多余代码