2012-01-24 43 views
33

Ai đó có thể giải thích cho tôi tại sao có sự khác biệt về thứ tự xử lý sự kiện đang được thực hiện tùy thuộc vào cách họ đã được đính kèm? Trong ví dụ bên dưới, tôi đang sử dụng các phương pháp .on().addEventListener() để xử lý một sự kiện cụ thể trên các phần tử DOM khác nhau.jQuery .on(); so với JavaScript .addEventListener();

jsfiddle: http://jsfiddle.net/etsS2/

Tôi nghĩ rằng trong ví dụ đặc biệt này theo thứ tự mà xử lý sự kiện sẽ được thực hiện sẽ phụ thuộc vào event-bubbling - vì vậy bắt đầu từ sự kiện ban đầu target và di chuyển lên đến document phần tử.

document.getElementById('outer').addEventListener('mouseup', function (event) { 
//$('#outer').on('mouseup', function (event) { 
    alert('This alert should not show up!'); 
}, false); 

Nếu tôi bỏ ghi chú phiên bản on(); mọi thứ hoạt động như mong đợi - là có một sự khác biệt trong cách jQuery xử lý sự kiện trái với thuần JavaScript?

Trả lời

22

Khi bạn sử dụng .on() ở cấp tài liệu, bạn đang chờ sự kiện phát bóng đến tận cùng thời điểm đó. Trình xử lý sự kiện cho bất kỳ vùng chứa trung gian nào đã được gọi.

Sự kiện "bong bóng" là quá trình mà trình duyệt tìm kiếm trình xử lý sự kiện đã đăng ký với cha mẹ của phần tử là người nhận ban đầu thực sự của sự kiện. Nó hoạt động trở lên trong cây DOM. Cấp tài liệu là kiểm tra mức cuối cùng. Do đó, trình xử lý của bạn đã đăng ký với .on() sẽ không chạy cho đến khi đạt đến cấp đó. Trong khi chờ đợi, trình xử lý sự kiện khác ở cấp "bên ngoài" được truy cập đầu tiên và nó được thực thi bởi trình duyệt.

Do đó, return false; trong trình xử lý đã đăng ký với .on() là khá nhiều vô ích, như sẽ là một cuộc gọi đến event.stopPropagation(). Ngoài ra, việc trộn đăng ký xử lý sự kiện bản địa với công việc mà một thư viện như jQuery sẽ làm có lẽ là một ý tưởng thực sự tồi trừ khi bạn nghiêm túc biết mình đang làm gì.

Đã có a question asked almost exactly like this one chỉ một chút trước đây ngày hôm nay.

+0

'return false' cũng có' event.preventDefault() 'cũng như' event.stopPropagation() 'trong trình xử lý sự kiện jQuery. – Jasper

+0

Lý do tại sao tôi tạo cấu trúc này là do thực tế là phần tử 'a.link' được thêm động và bằng cách nào đó tôi cần ngăn chặn div bên ngoài xử lý sự kiện cụ thể đó - làm cách nào tôi có thể đạt được điều đó? Vì vậy, về cơ bản bạn có nghĩa là điều này: $ (tài liệu) .on ('mouseup', 'a.link' ...) là bằng này: $ ('a.link'). Sống ('mouseup', ...)? – MonkeyCoder

+1

Có - cách duy nhất một cơ chế như '.live()', '.delegate()', hoặc '.on()' mới có thể hoạt động thông qua sủi bọt, và bọt hoạt động từ trong ra ngoài. Thay vào đó, bạn có thể đảm bảo rằng trình lắng nghe sự kiện cho các phần tử được thêm động được liên kết trực tiếp với các phần tử khi chúng được thêm vào DOM. – Pointy

12

Nhìn vào phiên bản addEventListener:

document.getElementById('outer').addEventListener('mouseup', function (event) { 
    alert('This alert should not show up!'); 
}, false); 

đó làm việc tốt vì đối số thứ ba là useCapture, trong đó xác định có hay không giai đoạn chụp của sự kiện này nên được sử dụng.

Khi bạn chuyển sang phiên bản jQuery:

$('#outer').on('mouseup', function (event) { 
    alert('This alert should not show up!'); 
}, false); 

Tôi nghĩ rằng những gì đang xảy ra là số thứ ba chỉ đơn giản ghi đè chức năng xử lý sự kiện của bạn và làm cho xử lý sự kiện để làm gì, nhưng return false; mà rõ ràng là không những gì có nghĩa là để xảy ra.

Từ jQuery docs (nhấn mạnh thêm):

Một chức năng để thực thi khi sự kiện này được kích hoạt. Giá trị false là cũng được cho phép làm viết tắt cho hàm chỉ đơn giản trả về false.

Tháo luận false và phiên bản jQuery sẽ làm việc một cách chính xác quá:

$('#outer').on('mouseup', function (event) { 
    alert('This alert should not show up!'); 
}); 

Lưu ý rằng alertnên xuất hiện, vì vậy phương pháp addEventListener đang làm việc một cách chính xác. Xem câu trả lời của @ Pointy về lý do tại sao.

Các vấn đề liên quan