- vừa được xem lúc

Bubbling and capturing in Javascript

0 0 24

Người đăng: phanvan

Theo Viblo Asia

Chúng ta sẽ bắt đầu bằng 1 ví dụ.

Bắt sự kiện onclick trên div, nhưng nó cũng sẽ kích khi chúng ta click vào nested tag <em> hoặc <code>:

 <div onclick="alert('The handler!')"> <em>If you click on <code>EM</code>, the handler on <code>DIV</code> runs.</em> </div>

Có phải hơi lạ phải không? Tại sao event onclick trên <div> kích hoạt khi click chuột vào <em>?

Bubbling

Nguyên tắc hoạt động của bubbling rất là đơn giản.

Khi một event xảy ra trên một phần tử, đầu tiên nó sẽ chạy các handler trên nó, sau đó là cha mẹ của nó, sau đó đến tất cả các tag cha bên ngoài khác.

Bây giờ chúng ta có FORM > DIV > P với event onclick trên mỗi tag.

 <style> body * { margin: 10px; border: 1px solid blue; } </style> <form onclick="alert('form')">FORM <div onclick="alert('div')">DIV <p onclick="alert('p')">P</p> </div> </form>

Khi click vào bên trong <p> nó sẽ chạy onclick:

  1. Trên <p>.
  2. Ra ngoài <div>.
  3. Ra ngoài <form>.
  4. Và tới document.

Nếu click trên <p>, chúng ta sẽ nhìn thấy 3 alert: p -> div -> form.

Quá trình này được gọi là "bubbling" bởi vì các event "bubbling" từ element bên trong lên qua cha mẹ giống như một bong bóng trong nước.

event.target

Một handler trên element cha có thể biết được chi tiết về nơi event thực sự xảy ra.

Phần tử trong cùng gây ra sự kiện này được gọi là target element, có thể truy cập dưới dạng event.target.

Chú ý sự khác nhau của this(=event.currentTarget) :
* event.target: là "target" element lúc init event, nó không thay đổi thông qua quá trình bubling.
* this: là element "current" , có một handler đang chạy trên nó.

Chẳng hạn, nếu chúng ta có handler duy nhất form.onclick, thì nó có thể bắt được tất cả các click chuột trong form. Bất kể nhấp chuột xảy ra ở đâu, nó sẽ bubbles lên <form> và chạy handler.

Trong handler form.click:
* this(=event.currentTarget) là <form> element bởi vì handler chạy trên nó.
* event.target là element cụ thể bên trong được click.

event.target bằng this khi click trực tiếp vào <form> element.

Stopping bubbling

Một bubbling event đi từ target element thẳng lên. Thông thường, nó đi lên cho đến <html>, sau đó đến document object, và một số sự kiện thậm chí đến windown, gọi tất cả các handler trên đường dẫn.

Nhưng handler nào có thể quyết định rằng event đã được xử lý đầy đủ và ngăn chặn bubbling, method event.stopPropagation() làm điều này.

Ví dụ, ở đây body.onclick không làm việc nếu click vào <button>:

 <body onclick="alert(`the bubbling doesn't reach here`)"> <button onclick="event.stopPropagation()">Click me</button> </body>

Không stop bubbling khi không cần

Capturing

Ở đây một giai đoạn khác của quá trình xử lý sự kiện được gọi là "capturing". Nó hiếm khi được sử dụng trong code thực tế, nhưng đôi khi có thể hữu ích.

Theo chuẩn DOM Events có 3 giai đoạn lan truyền của event:

  1. Capturing phase - event đi xuống element.
  2. Target phase - event tới element target.
  3. Bubbling phase - event bubles tuef element.

Dưới đây là hình ảnh khi click vào <td> bên trong table:

Khi click vào <td>, event trước tiên đi từ window xuống element (capturing phase), sau đó nó đến mục tiêu và kích hoạt ở đó (target phase), sau đó nó đi lên (bubbling phase), gọi handler trên đường đi của nó.

Trước đó chúng ta chỉ nói về bubbling, bởi vì capturing pharse ít khi được sử dụng.

Handler được thêm bằng on<event> -property, sử dụng HTML attributes hoặc sử dụng addEventListener(event, handler) chúng ta chỉ chạy trên pharse 2,3 (target pharse, bubbling pharse).

Để bắt sự kiện capturing pharse , chúng ta cần set caturing: true:

 elem.addEventListener(..., {capture: true}) // or elem.addEventListener(..., true)

Bây giờ chúng ta sẽ nhìn 2 pharse:

 <style> body * { margin: 10px; border: 1px solid blue; } </style> <form>FORM <div>DIV <p>P</p> </div> </form> <script> for(let elem of document.querySelectorAll('*')) { elem.addEventListener("click", e => alert(`Capturing: ${elem.tagName}`), true); elem.addEventListener("click", e => alert(`Bubbling: ${elem.tagName}`)); } </script>

Nếu click vào p:

  1. HTMLBODYFORMDIV (capturing phase).
  2. P (target phrase).
  3. DIVFORMBODYHTML (bubbling phase).

Để loại bỏ event capturing pharse chúng ta sử dụng removeEventListener(..., true).

Bình luận

Bài viết tương tự

- vừa được xem lúc

Giới thiệu Typescript - Sự khác nhau giữa Typescript và Javascript

Typescript là gì. TypeScript là một ngôn ngữ giúp cung cấp quy mô lớn hơn so với JavaScript.

0 0 500

- vừa được xem lúc

Bạn đã biết các tips này khi làm việc với chuỗi trong JavaScript chưa ?

Hi xin chào các bạn, tiếp tục chuỗi chủ đề về cái thằng JavaScript này, hôm nay mình sẽ giới thiệu cho các bạn một số thủ thuật hay ho khi làm việc với chuỗi trong JavaScript có thể bạn đã hoặc chưa từng dùng. Cụ thể như nào thì hãy cùng mình tìm hiểu trong bài viết này nhé (go).

0 0 414

- vừa được xem lúc

Một số phương thức với object trong Javascript

Trong Javascript có hỗ trợ các loại dữ liệu cơ bản là giống với hầu hết những ngôn ngữ lập trình khác. Bài viết này mình sẽ giới thiệu về Object và một số phương thức thường dùng với nó.

0 0 136

- vừa được xem lúc

Tìm hiểu về thư viện axios

Giới thiệu. Axios là gì? Axios là một thư viện HTTP Client dựa trên Promise.

0 0 117

- vừa được xem lúc

Imports và Exports trong JavaScript ES6

. Giới thiệu. ES6 cung cấp cho chúng ta import (nhập), export (xuất) các functions, biến từ module này sang module khác và sử dụng nó trong các file khác.

0 0 93

- vừa được xem lúc

Bài toán đọc số thành chữ (phần 2) - Hoàn chỉnh chương trình dưới 100 dòng code

Tiếp tục bài viết còn dang dở ở phần trước Phân tích bài toán đọc số thành chữ (phần 1) - Phân tích đề và những mảnh ghép đầu tiên. Bạn nào chưa đọc thì có thể xem ở link trên trước nhé.

0 0 229