• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Day 5性能优化和调试 | 青训营

武飞扬头像
并没有什么luck
帮助1

优化 JavaScript 代码可以显著提高性能和用户体验。以下是一些常见的优化技术,包括减少重绘和重排、使用节流和防抖技术以及使用性能分析工具等:

减少重绘和重排

避免频繁的 DOM 操作,尽量一次性进行批量处理。

  • 使用 CSS 类而不是直接操作样式属性,以减少重绘和重排的次数。
  • 使用 documentFragment 或离线 DOM 进行复杂的 DOM 操作,最后再将其添加到文档中,以减少重排的次数。

区别

重绘(Repaint)和重排(Reflow)是与浏览器渲染页面相关的两个概念,它们在性能优化中具有重要意义。以下是它们的区别:

重绘(Repaint): 重绘指的是当元素的可见样式发生变化,但布局(位置和大小)没有改变时,浏览器会重新绘制(repaint)该元素。重绘不涉及重新计算布局,只是将新的样式应用到元素上,使其显示更新的外观。例如,改变元素的颜色或背景色。

重排(Reflow): 重排指的是当元素的布局属性发生变化,需要浏览器重新计算元素的大小和位置时,会触发重排操作。重排会涉及重新计算布局,并重新绘制受影响的元素及其子元素。例如,改变元素的宽度、高度、位置、添加或删除元素等操作都会导致重排。

重绘和重排的区别在于是否涉及布局的计算和调整。重绘只是重新绘制元素的外观,而重排不仅会重新绘制元素,还会重新计算和调整元素的布局。

在性能优化中,重排的成本比重绘高得多,因为它涉及布局的计算和调整,可能会引起整个页面的重排和重绘。频繁的重排操作会导致页面性能下降,因此在代码编写时,应尽量减少重排的发生。

避免手段

一些减少重排和重绘的技术包括:

  • 使用 CSS3 的 transform 属性替代 topleft 等属性来进行位移操作,因为 transform 不会引起重排。
  • 在进行多次 DOM 操作时,使用文档片段(documentFragment)进行批量操作,最后一次性添加到文档中,减少重排次数。
  • 避免频繁读取布局信息(例如使用 offsetTopoffsetLeft 等属性),因为这会导致浏览器强制进行重排。
  • 使用 CSS 类名的切换来集中修改样式,而不是直接操作样式属性。

通过减少重排和重绘的次数,可以提高页面的性能和响应速度。

使用节流和防抖技术:

节流(Throttling)

限制在一定时间间隔内执行某个操作的频率。例如,在处理滚动事件时,可以使用节流来限制处理函数的调用频率。

function throttle<T extends unknown[]>(
  func: (...args: T) => void,
  delay: number
): (...args: T) => void {
  let timerId: NodeJS.Timeout | null;

  return function (...args: T) {
    if (!timerId) {
      timerId = setTimeout(() => {
        func.apply(this, args);
        timerId = null;
      }, delay);
    }
  };
}

function handleScroll() {
  console.log('Scroll event throttled');
}

const throttledScroll = throttle(handleScroll, 200);
window.addEventListener('scroll', throttledScroll);

防抖(Debouncing)

在一系列连续事件发生后,只执行一次操作。例如,在处理输入框的输入事件时,可以使用防抖来延迟处理函数的执行,直到用户停止输入一段时间。

function debounce<T extends unknown[]>(
  func: (...args: T) => void,
  delay: number
): (...args: T) => void {
  let timerId: NodeJS.Timeout;

  return function (...args: T) {
    clearTimeout(timerId);
    timerId = setTimeout(() => {
      func.apply(this, args);
    }, delay);
  };
}

function handleInput() {
  console.log('Input debounced');
}

const debouncedInput = debounce(handleInput, 300);
input.addEventListener('input', debouncedInput);

优化循环和迭代:

避免在循环中进行昂贵的操作,例如 DOM 操作或复杂的计算。尽量将这些操作移到循环外部或使用更高效的算法。 使用合适的循环方式,例如 for 循环比 forEach 循环更高效。

使用异步操作:

将耗时的操作(例如网络请求或计算密集型任务)放在异步函数中执行,以避免阻塞主线程。

使用性能分析工具:

使用浏览器的开发者工具(如 Chrome 开发者工具)进行性能分析,查找性能瓶颈和优化的机会。 使用 JavaScript 性能分析工具(如 Lighthouse、Webpack Bundle Analyzer、Chrome DevTools 的 Performance 面板等)进行更深入的性能分析和优化建议。

压缩和缓存:

压缩 JavaScript 代码,减小文件大小,加快下载速度。可以使用工具如 UglifyJS、Terser 等进行代码压缩。 使用浏览器缓存机制,利用缓存来减少网络请求,提高页面加载速度。

懒加载和预加载:

对于大型页面或资源密集型应用,可以使用懒加载技术,延迟加载不必要的资源,只在需要时再进行加载。 针对已知将来需要使用的资源,可以使用预加载技术,在页面加载完成后立即开始加载这些资源,以提前获取并缓存。

懒加载

随着网页发展,对检测某个(些)元素是否出现在可视窗相关的需求越来越多,比如:

  • 当页面滚动时,懒加载图片或其他内容。
  • 实现“可无限滚动”网站,也就是当用户滚动网页时直接加载更多内容,无需翻页。
  • 对某些元素进行埋点曝光
  • 滚动到相应区域来执行相应动画或其他任务。 IntersectionObserver的诞生

IntersectionObserver:是以new的形式声明一个对象,接收两个参数callbackoptions;option是一个对象,包含三个属性:

1.root,所监听对象的具体祖先元素。如果未传入值或值为null,则默认使用顶级文档的视窗(一般为html)。

2.rootMargin,计算交叉时添加到根(root)边界盒bounding box的矩形偏移量, 可以有效的缩小或扩大根的判定范围从而满足计算需要。所有的偏移量均可用像素(px)或百分比(%)来表达, 默认值为"0px 0px 0px 0px"。

3.threshold

// 使用 Intersection Observer API 监听元素是否进入可视区域
const io = new IntersectionObserver((entries) => {
  entries.forEach((item) => {
    if (item.isIntersecting) {
      item.target.src = item.target.dataset.src;
      io.unobserve(item.target);
    }
  });
}, {
  root: document.querySelector('.root')
});

// 遍历所有需要懒加载的元素,添加 Intersection Observer 监听
imgList.forEach((img) => io.observe(img));

我们使用 Intersection Observer API 监听带有 img 类名的元素是否进入可视区域。一旦元素进入可视区域,就会触发回调函数,加载对应的懒加载内容

预加载

一个常见的预加载场景是在页面加载完成后,预加载下一个页面所需的关键资源,以提前获取并缓存这些资源,以便在用户切换到下一个页面时能够立即使用它们

// 创建一个新的Image对象
const preloader = new Image();

// 预加载的资源URL
const nextPageResource = 'https://example.com/next-page-resource.jpg';

// 预加载资源
preloader.src = nextPageResource;

// 在需要使用预加载资源的地方,检查资源是否已加载完成
if (preloader.complete) {
  // 资源已加载完成,可以立即使用
  handleNextPage();
} else {
  // 资源尚未加载完成,监听load事件,在加载完成后执行操作
  preloader.addEventListener('load', handleNextPage);
}

// 处理下一个页面的操作
function handleNextPage() {
  // 执行需要在下一个页面中使用的操作
  console.log('Next page resources are ready to use!');
  // ...
}

这些技术只是优化 JavaScript 代码性能的一部分,具体的优化策略和技术选择应根据具体的应用场景进行调整和实施。同时,定期进行性能测试和分析,以便了解和改进应用的性能瓶颈。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgbcfbf
系列文章
更多 icon
同类精品
更多 icon
继续加载