性能优化
程序员文章站
2022-05-12 16:32:56
...
原则
- 多使用内存,缓存或者其他方法(非硬盘)
- 减少 CPU 计算,减少网络请求
性能优化从加载页面和静态资源,页面渲染入手
-
加载资源优化
-
静态资源的压缩合并
例如几个
<script>
合并成一个,可以使用构建工具完成,也可以手动实现 -
静态资源缓存
通过链接名称控制缓存。例如
<script src="abc_1.js">
,只有内容改变,链接名称才会改变,才会加载新的文件,不然可以直接使用缓存。 - 使用 CDN(Content Delivery Network,即内容分发网络,其基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快、更稳定。) 让资源加载更快
- 使用 SSR(Server Side Render) 后端渲染,数据直接输出到 HTML 里面
-
-
渲染优化
- CSS 放前面,JS 放后面
-
懒加载(图片懒加载,下拉加载更多)
<img id="img" src="preview.png" data-realsrc="abc.png" /> <script> var img = document.getElementById('img'); img.src = img.getAttribute('data-realsrc'); </script>
-
减少 DOM 查询,对 DOM 查询做缓存
// 未缓存 DOM 查询 for (var i = 0; i < document.getElementsByTagName('p').length; i++) { // todo } // 缓存了 DOM 查询 var pList = document.getELementsByTagName('p') for (var i = 0; i < pList.length; i++) { // todo }
-
减少 DOM 查询,多个操作尽量合并在一起执行(合并插入)
var listNode = document.getElementById('list') // 要插入 10 个 li 标签 var frag = document.createDocumentFragment(); var li; for (var i = 0; i < 10; i++) { li = document.createElement('li'); li.innerHTML = 'List Item ' + i; frag.appendChild(li); } listNode.appendChild(frag);
-
事件节流
var textarea = document.getElementById('text'); var timeoutId; textarea.addEventListener('keyup', function () { if (timeoutId) { clearTimeout(timeoutId); } timeoutId = setTimeout(function () { // 触发 change 事件 }, 100); })
-
尽早执行操作(如 DOMContentLoaded)
window.addEventListener('load', function () { // 页面的全部资源加载完才可执行,包括图片和视频等 }) document.addEventListener('DOMContentLoaded', function () { // DOM渲染完即可执行,此时图片,视频可能还没有加载完 })
函数节流和函数防抖
函数防抖(debounce):当调用动作过 n 毫秒,才会执行该动作,若在这 n 毫秒内又调用此动作则将重新计算执行时间
函数节流(throttle):预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个新周期
函数防抖(debounce)与函数节流(throttle)都是为了限制函数的执行频次,以优化函数触发频率过高导致的响应速度跟不上触发频率,出现延迟,假死或卡顿的现象。
一般用于以下的情况:
- window队形的 resize,scroll 事件
- 拖拽时的 mousemove 事件
- 文字输入,自动完成的 keyup 事件
实现
// 函数防抖
function _debounce (fn, wait) {
var timer = null;
return function () {
// 每次触发 scroll handler 时先清除定时器
clearTimeout(timer);
// 指定 xx ms 后触发真正想执行的操作 handler
timer = setTimeout(fn, wait);
}
}
// 实际想绑定在 scroll 事件上的 handler
function _print () {
console.log('tamir');
}
// 采用了防抖动
window.addEventListener('scroll', _debounce(_print, 500));
// 没采用防抖动
window.addEventListener('scroll', _print);
// 函数节流
function _throttle (fn, wait, time) {
var previous = null;// 记录上一次运行时间
var timer = null;
return function () {
// + 相当于 valueOf()
var now = +new Date();
if (!previous) {
previous = now;
}
var context = this;
var args = arguments;
clearTimeout(timer);
// 当上一次执行的时间与当前的时间差大于设置的执行间隔时长,就主动执行一次
if (now - previous > time) {
fn.apply(this, args);
previous = now;// 执行函数后,马上记录当前时间
} else { // 没达到触发间隔,重新设定定时器
timer = setTimeout(fn, wait);
}
}
}
function _print () {
console.log('tamir');
}
window.addEventListener('scroll', _throttle(_print, 500, 1000));
上一篇: 双向循环链表
下一篇: C语言编写一九九乘法口诀表