iT邦幫忙

2024 iThome 鐵人賽

DAY 27
0
JavaScript

入門JavaScript系列 第 27

JavaScript與事件處理(2)

  • 分享至 

  • xImage
  •  

JavaScript 與事件處理的進階應用,可以讓你在開發更複雜的應用程序時更精確地控制互動行為,並提升性能與靈活性。這些進階技術涵蓋了自訂事件、節流與防抖、事件捕獲、委派的深度應用等,這些技術使得開發者能夠創建更加高效且可維護的應用。

1. 自訂事件(Custom Events)

除了內建的事件類型,JavaScript 還允許開發者創建自訂事件,這在需要觸發應用特定邏輯時非常有用。自訂事件可以用 CustomEvent 來創建,並且能夠攜帶自定義數據。

範例:創建和觸發自訂事件

<button id="myButton">Trigger Custom Event</button>

<script>
  const myButton = document.getElementById('myButton');

  // 創建自訂事件,並包含一些自定義數據
  const customEvent = new CustomEvent('myCustomEvent', {
    detail: { message: 'Hello, this is a custom event!' }
  });

  // 監聽自訂事件
  document.addEventListener('myCustomEvent', function(event) {
    console.log(event.detail.message);  // 取得自訂數據
  });

  // 在按鈕點擊時觸發自訂事件
  myButton.addEventListener('click', function() {
    document.dispatchEvent(customEvent);
  });
</script>

在這個範例中,我們創建了一個名為 myCustomEvent 的事件,並攜帶了一些數據。當用戶點擊按鈕時,這個自訂事件會被觸發,並且處理程序可以讀取這些自訂數據。

2. 節流(Throttling)與防抖(Debouncing)

當處理高頻次事件(如滾動或窗口縮放)時,節流和防抖技術可以有效地減少事件處理的次數,從而提高性能。

  • 節流(Throttling):限制函數的執行頻率,即在指定的時間段內只允許函數執行一次。
  • 防抖(Debouncing):將函數的執行延遲到事件停止後的一段時間,這在響應快速重複觸發的事件時特別有用。

範例:節流(Throttle)

<script>
  function throttle(func, delay) {
    let lastTime = 0;
    return function(...args) {
      const now = new Date().getTime();
      if (now - lastTime >= delay) {
        lastTime = now;
        func.apply(this, args);
      }
    };
  }

  // 滾動事件的節流應用
  window.addEventListener('scroll', throttle(function() {
    console.log('Throttled scroll event:', new Date().toLocaleTimeString());
  }, 1000));
</script>

這裡的 throttle 函數保證了滾動事件每隔 1 秒才會觸發一次,避免了滾動時頻繁觸發過多的事件處理,從而提升性能。

範例:防抖(Debounce)

<script>
  function debounce(func, delay) {
    let timer;
    return function(...args) {
      clearTimeout(timer);
      timer = setTimeout(() => func.apply(this, args), delay);
    };
  }

  // 窗口大小改變的防抖應用
  window.addEventListener('resize', debounce(function() {
    console.log('Debounced resize event:', new Date().toLocaleTimeString());
  }, 500));
</script>

防抖技術保證只有在用戶停止改變窗口大小後 500 毫秒,事件處理函數才會被觸發,這有助於避免多次重複執行不必要的計算。

3. 事件捕獲(Event Capturing)與冒泡的進階應用

事件的傳遞機制分為三個階段:捕獲階段(從根到目標元素)、目標階段、冒泡階段(從目標元素到根)。通常我們只關注冒泡階段,但事件捕獲在某些情況下非常有用,尤其是在需要提前攔截事件時。

範例:事件捕獲的使用

<div id="parentDiv">
  <button id="childButton">Click Me</button>
</div>

<script>
  const parentDiv = document.getElementById('parentDiv');
  const childButton = document.getElementById('childButton');

  // 在捕獲階段監聽事件
  parentDiv.addEventListener('click', function() {
    console.log('Parent captured!');
  }, true);  // 第三個參數為 true,表示使用捕獲階段

  childButton.addEventListener('click', function() {
    console.log('Button clicked!');
  });
</script>

在這個例子中,由於 true 被傳遞給 addEventListener 的第三個參數,父元素在捕獲階段先攔截到 click 事件,然後按鈕才會處理事件。

4. 事件委派的進階應用

事件委派是優化事件監聽器的關鍵技術,特別是在處理大量動態生成的元素時。進階應用中,委派可以處理多個不同的事件,或者根據事件目標的屬性來進行不同的操作。

範例:動態處理多種類型的事件

<ul id="myList">
  <li data-action="edit">Edit</li>
  <li data-action="delete">Delete</li>
  <li data-action="share">Share</li>
</ul>

<script>
  const myList = document.getElementById('myList');

  myList.addEventListener('click', function(event) {
    const action = event.target.getAttribute('data-action');
    switch (action) {
      case 'edit':
        console.log('Edit item');
        break;
      case 'delete':
        console.log('Delete item');
        break;
      case 'share':
        console.log('Share item');
        break;
      default:
        console.log('Unknown action');
    }
  });
</script>

這個例子展示了如何利用事件委派來動態處理不同的操作,通過檢查 data-action 屬性來確定具體要執行的動作。

5. 事件的傳遞控制:stopPropagation()preventDefault()

當處理某些事件時,你可能需要控制事件的傳遞,這可以通過 stopPropagation() 阻止事件冒泡或捕獲,或者使用 preventDefault() 阻止元素的預設行為。

範例:阻止事件冒泡與預設行為

<a href="https://example.com" id="myLink">Click Me</a>

<script>
  const myLink = document.getElementById('myLink');

  myLink.addEventListener('click', function(event) {
    event.preventDefault();  // 阻止鏈接跳轉
    event.stopPropagation();  // 阻止事件冒泡
    console.log('Link clicked, but default action prevented');
  });

  document.body.addEventListener('click', function() {
    console.log('Body clicked!');
  });
</script>

在這裡,點擊鏈接後會阻止其跳轉到其他頁面,也阻止了事件冒泡到 body 的事件監聽器。

6. oncepassive 選項的應用

addEventListener 的第三個參數可以是一個配置對象,用來控制事件處理的方式:

  • once: true:讓事件監聽器只觸發一次。
  • passive: true:告訴瀏覽器這個事件處理程序不會調用 preventDefault(),這能優化像滾動事件這樣的性能。

範例:使用 oncepassive

<button id="myButton">Click Me</button>

<script>
  const button = document.getElementById('myButton');

  // 事件監聽器只會觸發一次
  button.addEventListener('click', function() {
    console.log('Button clicked!');
  }, { once: true });

  // 優化滾動事件的性能
  window.addEventListener('scroll', function() {
    console.log('Scroll event');
  }, { passive: true });
</script>

在這個範例中,按鈕點擊事件只會被處理一次,而

滾動事件因為使用了 passive,瀏覽器不再需要考慮阻止滾動,從而提升性能。

總結

JavaScript 與事件處理的進階應用,能夠幫助開發者更好地管理事件,優化性能,並提高代碼的可讀性和靈活性。無論是自訂事件、事件委派,還是使用節流與防抖技術,這些工具都可以用來構建更高效、可維護的應用。掌握這些技巧後,你可以更加自信地處理複雜的交互需求。


上一篇
JavaScript與事件處理(1)
下一篇
JavaScript與HTML(1)
系列文
入門JavaScript30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言