Skip to content

性能优化与 DOM

1. 防抖 (Debounce)

在事件被触发 n 秒后再执行回调。如果在这 n 秒内又被触发,则重新计时。

适用场景:搜索框输入、窗口大小调整。

javascript
/**
 * @param {function} fn - 需要防抖的函数
 * @param {number} delay - 延迟时间
 */
function debounce(fn, delay) {
  let timer;
  return function (...args) {
    if (timer) clearTimeout(timer);
    timer = setTimeout(() => {
      fn.apply(this, args);
    }, delay);
  };
}

// 示例
const handleInput = debounce((val) => {
  console.log('Searching for:', val);
}, 500);

2. 节流 (Throttle)

规定在一个单位时间内,只能触发一次函数。如果这个单位时间内触发多次函数,只有一次生效。

适用场景:滚动加载、高频点击。

javascript
/**
 * @param {function} fn - 需要节流的函数
 * @param {number} delay - 时间间隔
 */
function throttle(fn, delay) {
  let lastTime = 0;
  return function (...args) {
    const now = Date.now();
    if (now - lastTime > delay) {
      lastTime = now;
      fn.apply(this, args);
    }
  };
}

## 3. 图片预加载 (Preloading)
适用于首屏大图、轮播图下一张等需要快速展示的资源。

```javascript
function preloadImage(url) {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.src = url;
    img.onload = () => resolve(img);
    img.onerror = (e) => reject(e);
  });
}

4. 图片懒加载 (Lazy Loading)

适用于长页面非首屏图片,比如商品列表、文章配图。原理是判断图片是否进入可视区域,进入后再设置 src 属性。

javascript
// 使用 IntersectionObserver 实现
function lazyLoadImages() {
  const images = document.querySelectorAll('img[data-src]');
  
  if ('IntersectionObserver' in window) {
    const observer = new IntersectionObserver((entries) => {
      entries.forEach(entry => {
        if (entry.isIntersecting) {
          const img = entry.target;
          img.src = img.dataset.src;
          img.removeAttribute('data-src');
          observer.unobserve(img);
        }
      });
    });

    images.forEach(img => observer.observe(img));
  }
}

// HTML 使用示例:
// <img data-src="real-image.jpg" src="placeholder.jpg" alt="懒加载示例">

5. 分片加载演示

(见同目录 HTML 文件)


## 3. 事件委托 (Event Delegation)

利用事件冒泡机制,将子元素的事件委托给父元素处理。

```javascript
/* 简化演示 (非完整实现) */
document.getElementById('parent-list').addEventListener('click', function (e) {
  // 检查点击的目标是否是我们关心的子元素
  if (e.target && e.target.nodeName === 'LI') {
    console.log('List item ', e.target.id, ' was clicked!');
  }
});

MIT Licensed | Keep Learning.