CodeGym /Các khóa học /Frontend SELF VI /Tối ưu hóa sự kiện

Tối ưu hóa sự kiện

Frontend SELF VI
Mức độ , Bài học
Có sẵn

9.1 Ủy quyền sự kiện

Làm việc với sự kiện trong JavaScript có thể đòi hỏi quản lý phức tạp để tối ưu hóa hiệu suất và cải thiện kiến trúc ứng dụng.

Tối ưu hóa làm việc với sự kiện trong JavaScript rất quan trọng để tạo ra các ứng dụng web có hiệu suất tốt, đặc biệt khi làm việc với nhiều phần tử. Trong bối cảnh này, ủy quyền sự kiện và ngăn chặn các bộ xử lý dư thừa đóng vai trò quan trọng.

Ủy quyền sự kiện là một mẫu mà trong đó bộ xử lý sự kiện được gắn vào phần tử cha, thay vì từng phần tử con riêng lẻ. Điều này cho phép quản lý hiệu quả các sự kiện cho số lượng lớn các phần tử con, vì bộ xử lý chỉ được gọi một lần cho phần tử cha, chứ không phải cho từng phần tử.

Ví dụ không có ủy quyền sự kiện:

HTML
    
      <!DOCTYPE html>
      <html>
        <head>
          <title>Ví dụ ủy quyền sự kiện</title>
        </head>
        <body>
          <ul id="list">
            <li>Phần tử 1</li>
            <li>Phần tử 2</li>
            <li>Phần tử 3</li>
          </ul>
          <script>
            const list = document.querySelector('ul');
            const items = document.querySelectorAll('#list li');

            items.forEach(item => {
              item.addEventListener('click', function(event) {
                const li = document.createElement('li');
                li.innerText = "Phần tử mới, sự kiện không hoạt động";
                list.appendChild(li);
                alert(`Bạn đã nhấn vào: ${event.target.textContent}`);
              });
            });
          </script>
        </body>
      </html>
    
  

Vấn đề: nếu danh sách phần tử thay đổi động, bạn sẽ cần thêm bộ xử lý cho từng phần tử mới.

Giải pháp — ví dụ với ủy quyền sự kiện:

HTML
    
      <!DOCTYPE html>
      <html>
        <head>
          <title>Ví dụ ủy quyền sự kiện</title>
        </head>
        <body>
          <ul id="list">
            <li>Phần tử 1</li>
            <li>Phần tử 2</li>
            <li>Phần tử 3</li>
          </ul>
          <script>
            const list = document.getElementById('list');
            list.addEventListener('click', function(event) {
              if (event.target.tagName === 'LI') {
                const li = document.createElement('li');
                li.innerText = "Phần tử mới, sự kiện sẽ hoạt động";
                list.appendChild(li);
                alert(`Bạn đã nhấn vào: ${event.target.textContent}`);
              }
            });
          </script>
        </body>
      </html>
    
  

Lợi ích:

  • Bộ xử lý chỉ được thêm vào phần tử cha
  • Các phần tử thêm vào động sẽ tự động có bộ xử lý sự kiện

9.2 Ngăn chặn các bộ xử lý dư thừa

Để tránh giảm hiệu suất, quan trọng là phải giảm thiểu số lượng bộ xử lý sự kiện, đặc biệt nếu chúng được gắn vào nhiều phần tử hoặc được gọi thường xuyên. Một số cách tiếp cận để tối ưu hóa:

1. Giảm số lượng bộ xử lý: sử dụng ủy quyền sự kiện để giảm số lượng bộ xử lý.

2. Sử dụng once trong addEventListener: nếu bộ xử lý sự kiện chỉ cần chạy một lần, sử dụng tùy chọn { once: true } khi thêm bộ xử lý.

Ví dụ:

HTML
    
      <!DOCTYPE html>
      <html>
        <head>
          <title>Ví dụ sự kiện một lần</title>
        </head>
        <body>
          <button id="myButton">Nhấn vào tôi!</button>
          <script>
            const button = document.getElementById('myButton');
            button.addEventListener('click', function(event) {
              alert('Bạn đã nhấn vào nút');
            }, { once: true });
          </script>
        </body>
      </html>
    
  

3. Debouncing và throttling: những kỹ thuật này hữu ích để tối ưu hóa các bộ xử lý sự kiện thường được gọi, như scroll hoặc resize.

9.3 Debouncing

Debouncing gộp nhiều lần gọi hàm kế tiếp thành một, chỉ được thực hiện sau khi dòng sự kiện đã dừng.

Ví dụ:

JavaScript
    
      function debounce(func, wait) {
        let timeout;
        return function(...args) {
          const context = this;
          clearTimeout(timeout);
          timeout = setTimeout(() => func.apply(context, args), wait);
        };
      }

      window.addEventListener('resize', debounce(() => {
        console.log('Window resized');
      }, 300));
    
  

Thử thay đổi kích thước cửa sổ để xem kết quả

Ví dụ debouncing

Trong ví dụ này, hàm tìm kiếm chỉ được gọi sau khi người dùng dừng nhập văn bản trong 300 mili giây.

HTML
    
      <!DOCTYPE html>
      <html>
        <head>
          <title>Ví dụ debouncing</title>
        </head>
        <body>
          <div style="min-height: 55px">
            <input type="text" id="searchInput" placeholder="Bắt đầu nhập tìm kiếm...">
            <div id="results"></div>
          </div>

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

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

            function performSearch(event) {
              const query = event.target.value;
              results.textContent = 'Tìm kiếm: ' + query;
              // Giả lập yêu cầu tới server
              setTimeout(() => {
                results.textContent = 'Bạn đã tìm kiếm: ' + query;
              }, 500);
            }

            const debouncedSearch = debounce(performSearch, 300);

            searchInput.addEventListener('input', debouncedSearch);
          </script>
        </body>
      </html>
    
  
HTML
    
      <!DOCTYPE html>
      <html>
        <head>
          <title>Ví dụ debouncing</title>
        </head>
        <body>
          <input type="text" id="searchInput" placeholder="Bắt đầu nhập tìm kiếm...">
          <div id="results"></div>

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

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

            function performSearch(event) {
              const query = event.target.value;
              results.textContent = 'Searching for: ' + query;
              // Giả lập yêu cầu tới server
              setTimeout(() => {
                results.textContent = 'Bạn đã tìm kiếm: ' + query;
              }, 500);
            }

            const debouncedSearch = debounce(performSearch, 300);

            searchInput.addEventListener('input', debouncedSearch);
          </script>
        </body>
      </html>
    
  

9.4 Throttling

Trolling Throttling đảm bảo rằng hàm sẽ được gọi không quá một lần trong một khoảng thời gian nhất định.

Ví dụ:

JavaScript
    
      function throttle(func, limit) {
        let inThrottle;
        return function(...args) {
          const context = this;
          if (!inThrottle) {
            func.apply(context, args);
            inThrottle = true;
            setTimeout(() => inThrottle = false, limit);
          }
        };
      }

      window.addEventListener('scroll', throttle(() => {
        console.log('Window scrolled');
      }, 300));
    
  

Một ví dụ khác về throttling

Trong ví dụ này, bộ xử lý cuộn được gọi không thường xuyên hơn mỗi 200 mili giây, điều này giúp ngăn ngừa quá tải trình duyệt khi các sự kiện cuộn diễn ra thường xuyên.

HTML
    
      <!DOCTYPE html>
      <html>
        <head>
          <title>Ví dụ throttling</title>
        </head>
        <body>
          <div id="scrollContainer" style="height: 200px; overflow-y: scroll;">
            <div style="height: 1000px;"></div>
          </div>
          <div id="status">Bắt đầu cuộn để thấy hiệu ứng</div>

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

            function throttle(func, limit) {
              let lastFunc;
              let lastRan;
              return function(...args) {
                const context = this;
                if (!lastRan) {
                  func.apply(context, args);
                  lastRan = Date.now();
                } else {
                  clearTimeout(lastFunc);
                  lastFunc = setTimeout(() => {
                    if ((Date.now() - lastRan) >= limit) {
                      func.apply(context, args);
                      lastRan = Date.now();
                    }
                  }, limit - (Date.now() - lastRan));
                }
              };
            }

            function handleScroll(event) {
              status.textContent = 'Cuộn... ' + new Date().toLocaleTimeString();
            }

            const throttledScroll = throttle(handleScroll, 200);

            scrollContainer.addEventListener('scroll', throttledScroll);
          </script>
        </body>
      </html>
    
  

9.5 Tối ưu hóa sự kiện với người nghe sự kiện thụ động

Người nghe sự kiện thụ động (passive event listeners) được sử dụng để cải thiện hiệu suất, đặc biệt khi xử lý sự kiện cuộn (scroll). Khi bộ xử lý sự kiện được thiết lập là thụ động, tức là nó không sẽ không gọi preventDefault(), điều này cho phép trình duyệt tối ưu hóa hiệu suất.

Ví dụ:

JavaScript
    
      window.addEventListener('scroll', function(event) {
        console.log('Scrolling');
      }, { passive: true });
    
  
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION