addEventListener vs onclick


704

Sự khác biệt giữa addEventListenervà là onclickgì?

var h = document.getElementById("a");
h.onclick = dothing1;
h.addEventListener("click", dothing2);

Đoạn mã trên nằm cùng nhau trong một tệp .js riêng biệt và cả hai đều hoạt động hoàn hảo.

Câu trả lời:


956

Cả hai đều đúng, nhưng không ai trong số chúng là "tốt nhất" mỗi lần, và có thể có một lý do mà nhà phát triển chọn sử dụng cả hai phương pháp.

Trình lắng nghe sự kiện (addEventListener và IE's Đính kèm)

Các phiên bản trước của Internet Explorer triển khai javascript khác với khá nhiều trình duyệt khác. Với các phiên bản dưới 9, bạn sử dụng phương thức attachEvent[ doc ], như thế này:

element.attachEvent('onclick', function() { /* do stuff here*/ });

Trong hầu hết các trình duyệt khác (bao gồm IE 9 trở lên), bạn sử dụng addEventListener[ doc ], như thế này:

element.addEventListener('click', function() { /* do stuff here*/ }, false);

Sử dụng phương pháp này ( các sự kiện DOM Cấp 2 ), bạn có thể đính kèm số lượng sự kiện không giới hạn về mặt lý thuyết cho bất kỳ yếu tố nào. Giới hạn thực tế duy nhất là bộ nhớ phía máy khách và các mối quan tâm về hiệu suất khác, khác nhau đối với mỗi trình duyệt.

Các ví dụ trên đại diện cho việc sử dụng một hàm ẩn danh [ doc ]. Bạn cũng có thể thêm một trình lắng nghe sự kiện bằng cách sử dụng tham chiếu hàm [ doc ] hoặc đóng [ doc ]:

var myFunctionReference = function() { /* do stuff here*/ }

element.attachEvent('onclick', myFunctionReference);
element.addEventListener('click', myFunctionReference , false);

Một tính năng quan trọng khác addEventListenerlà tham số cuối cùng, điều khiển cách người nghe phản ứng với các sự kiện sủi bọt [ doc ]. Tôi đã chuyển sai trong các ví dụ, đây là tiêu chuẩn cho khoảng 95% trường hợp sử dụng. Không có đối số tương đương cho attachEventhoặc khi sử dụng các sự kiện nội tuyến.

Sự kiện nội tuyến (HTML onclick = "" property và Element.onclick)

Trong tất cả các trình duyệt hỗ trợ javascript, bạn có thể đặt một trình nghe sự kiện nội tuyến, nghĩa là ngay trong mã HTML. Bạn có thể đã thấy điều này:

<a id="testing" href="#" onclick="alert('did stuff inline');">Click me</a>

Hầu hết các nhà phát triển có kinh nghiệm trốn tránh phương pháp này, nhưng nó hoàn thành công việc; nó đơn giản và trực tiếp Bạn không được sử dụng các bao đóng hoặc các hàm ẩn danh ở đây (mặc dù trình xử lý là một hàm ẩn danh của các loại) và khả năng kiểm soát phạm vi của bạn bị hạn chế.

Phương pháp khác mà bạn đề cập:

element.onclick = function () { /*do stuff here */ };

... là tương đương với javascript nội tuyến ngoại trừ việc bạn có nhiều quyền kiểm soát phạm vi hơn (vì bạn đang viết một tập lệnh chứ không phải HTML) và có thể sử dụng các hàm ẩn danh, tham chiếu hàm và / hoặc đóng.

Hạn chế đáng kể với các sự kiện nội tuyến là không giống như các trình lắng nghe sự kiện được mô tả ở trên, bạn chỉ có thể có một sự kiện nội tuyến được chỉ định. Các sự kiện nội tuyến được lưu trữ dưới dạng một thuộc tính / thuộc tính của phần tử [ doc ], có nghĩa là nó có thể được ghi đè.

Sử dụng ví dụ <a>từ HTML ở trên:

var element = document.getElementById('testing');
element.onclick = function () { alert('did stuff #1'); };
element.onclick = function () { alert('did stuff #2'); };

... Khi bạn nhấp vào phần tử, bạn sẽ chỉ thấy "Đã làm thứ 2" - bạn ghi đè lên phần được gán đầu tiên của thuộc onclicktính bằng giá trị thứ hai và bạn cũng ghi đè lên thuộc tính HTML nội tuyến gốc onclick. Kiểm tra nó ở đây: http://jsfiddle.net/jpgah/ .

Nói rộng ra, không sử dụng các sự kiện nội tuyến . Có thể có các trường hợp sử dụng cụ thể cho nó, nhưng nếu bạn không chắc chắn 100% bạn có trường hợp sử dụng đó, thì bạn không và không nên sử dụng các sự kiện nội tuyến.

Javascript hiện đại (Angular và tương tự)

Vì câu trả lời này ban đầu được đăng, các khung javascript như Angular đã trở nên phổ biến hơn rất nhiều. Bạn sẽ thấy mã như thế này trong một mẫu Angular:

<button (click)="doSomething()">Do Something</button>

Điều này trông giống như một sự kiện nội tuyến, nhưng nó không phải là. Loại mẫu này sẽ được phiên mã thành mã phức tạp hơn, sử dụng các trình lắng nghe sự kiện đằng sau hậu trường. Tất cả mọi thứ tôi đã viết về các sự kiện ở đây vẫn được áp dụng, nhưng bạn đã bị loại bỏ khỏi lớp bụi bẩn ít nhất một lớp. Bạn nên hiểu các loại hạt và bu lông, nhưng nếu các cách thực hành tốt nhất trong khung JS hiện đại của bạn liên quan đến việc viết loại mã này trong một mẫu, đừng cảm thấy như bạn đang sử dụng một sự kiện nội tuyến - bạn không làm vậy.

Tốt nhất?

Câu hỏi là một vấn đề tương thích và cần thiết của trình duyệt. Bạn có cần đính kèm nhiều hơn một sự kiện vào một yếu tố không? Bạn sẽ trong tương lai chứ? Odds là, bạn sẽ. Đính kèm và addEventListener là cần thiết. Nếu không, một sự kiện nội tuyến có vẻ như họ sẽ thực hiện mánh khóe, nhưng bạn được phục vụ tốt hơn nhiều để chuẩn bị cho một tương lai, mặc dù điều đó dường như không thể xảy ra, ít nhất là có thể dự đoán được. Có một cơ hội bạn sẽ phải chuyển sang những người nghe sự kiện dựa trên JS, vì vậy bạn cũng có thể bắt đầu từ đó. Đừng sử dụng các sự kiện nội tuyến.

jQuery và các khung javascript khác gói gọn việc triển khai các sự kiện DOM cấp 2 khác nhau trong các mô hình chung để bạn có thể viết mã tuân thủ trình duyệt chéo mà không phải lo lắng về lịch sử của IE như là một kẻ nổi loạn. Cùng mã với jQuery, tất cả các trình duyệt chéo và sẵn sàng khuấy động:

$(element).on('click', function () { /* do stuff */ });

Mặc dù vậy, đừng chạy ra ngoài và kiếm một khuôn khổ cho điều này. Bạn có thể dễ dàng cuộn tiện ích nhỏ của riêng mình để chăm sóc các trình duyệt cũ hơn:

function addEvent(element, evnt, funct){
  if (element.attachEvent)
   return element.attachEvent('on'+evnt, funct);
  else
   return element.addEventListener(evnt, funct, false);
}

// example
addEvent(
    document.getElementById('myElement'),
    'click',
    function () { alert('hi!'); }
);

Hãy dùng thử: http://jsfiddle.net/bmArj/

Cân nhắc tất cả những điều đó, trừ khi tập lệnh bạn đang xem có tính đến sự khác biệt của trình duyệt theo một cách khác (mã không được hiển thị trong câu hỏi của bạn), phần sử dụng addEventListenersẽ không hoạt động trong các phiên bản IE dưới 9.

Tài liệu và đọc liên quan


14
xin lỗi vì đã va chạm nhưng chỉ muốn đưa ra một phiên bản cô đọng cho chức năng của bạn (fiddle: jsfiddle.net/bmArj/153 ) -function addEvent(element, myEvent, fnc) { return ((element.attachEvent) ? element.attachEvent('on' + myEvent, fnc) : element.addEventListener(myEvent, fnc, false)); }
Deryck

10
@Gaurav_soni Không. Tên của hàm và tất cả mã mà nó chứa đã được hiển thị trong tệp javascript, ở dạng bản rõ. Bất cứ ai cũng có thể mở bảng điều khiển web và thực thi hoặc thao tác bất kỳ javascript nào. Nếu javascript của bạn chứa bất cứ điều gì có thể gây rủi ro bảo mật nếu nó bị phơi bày ra công chúng, thì bạn đã gặp vấn đề lớn vì nó đã bị phơi bày ra công chúng.
Chris Baker

4
Miễn là chúng tôi cô đọng thuật toán này, chúng tôi cũng có thể đi theo mọi cách: function addEvent(e,n,f){return e.attachEvent?e.attachEvent('on'+n,f):e.addEventListener(n,f,!!0)}<< Với 98 ký tự, cái này nhỏ hơn 40%!
Trevor

3
@Trevor Vì tò mò, tại sao !! 0? Tại sao không! 1 hay chỉ 0?
Chris Baker

2
@AdrianMoisa Câu trả lời này được viết vào thời điểm AngularJS là một điều mới đang gia tăng và thực tế phổ biến vẫn là "tăng cường tiến bộ" - nghĩa là viết một tài liệu HTML theo cách có thể hoạt động với hoặc không có javascript. Theo quan điểm đó, các sự kiện ràng buộc từ javascript sẽ là cách thực hành tốt nhất. Ngày nay, tôi không nghĩ nhiều người lo lắng quá nhiều về việc tăng cường tiến bộ, đặc biệt là không xem xét đến sự phổ biến của những thứ như Angular. Vẫn còn một số tranh cãi về các sự kiện nội tuyến (không sử dụng Angular), nhưng đó là phong cách hơn là chất.
Chris Baker

193

Sự khác biệt bạn có thể thấy nếu bạn có một vài chức năng khác:

var h = document.getElementById('a');
h.onclick = doThing_1;
h.onclick = doThing_2;

h.addEventListener('click', doThing_3);
h.addEventListener('click', doThing_4);

Chức năng 2, 3 và 4 hoạt động, nhưng 1 thì không. Điều này là do addEventListenerkhông ghi đè trình xử lý sự kiện hiện có, trong khi onclickghi đè bất kỳ onclick = fntrình xử lý sự kiện hiện có .

Tất nhiên, sự khác biệt đáng kể khác là onclicksẽ luôn hoạt động, trong khi addEventListenerkhông hoạt động trong Internet Explorer trước phiên bản 9. Bạn có thể sử dụng tương tự attachEvent(có cú pháp hơi khác nhau) trong IE <9.


18
Đó là một lời giải thích rất rõ ràng! Đúng luận điểm. Vì vậy, nếu tôi cần nhiều chức năng cho một sự kiện, tôi bị mắc kẹt với addEventListener và tôi phải viết thêm mã cho AttachEvent chỉ để đệm IE.
William Sham

4
2, 3 và 4 nên được đặt tên là dos somebody. 1 bị ghi đè bởi 2 và không bao giờ được gọi.
DragonLord ngày 7 tháng

Quả thực là một lời giải thích rất rõ ràng và chính xác. Có thể là nó thực sự có ý nghĩa hơn khi đặt tên cho các hàm 'doT Breath_1', v.v. (Nếu bạn vẫn muốn phục vụ cho IE <9, hãy xem câu trả lời của Chris.)
Frank Conijn

61

Trong câu trả lời này, tôi sẽ mô tả ba phương pháp xác định trình xử lý sự kiện DOM.

element.addEventListener()

Mã ví dụ:

element.addEventListener() có nhiều ưu điểm:

  • Cho phép bạn đăng ký xử lý sự kiện không giới hạn và loại bỏ chúng với element.removeEventListener().
  • useCapturetham số, cho biết bạn muốn xử lý sự kiện trong giai đoạn bắt hoặc sủi bọt . Xem: Không thể hiểu thuộc tính useCapture trong addEventListener .
  • Quan tâm về ngữ nghĩa . Về cơ bản, nó làm cho việc xử lý đăng ký sự kiện rõ ràng hơn. Đối với người mới bắt đầu, một lệnh gọi hàm làm cho rõ ràng có điều gì đó xảy ra , trong khi việc gán sự kiện cho một số thuộc tính của phần tử DOM ít nhất là không trực quan.
  • Cho phép bạn tách cấu trúc tài liệu (HTML) và logic (JavaScript) . Trong các ứng dụng web nhỏ có vẻ như không quan trọng, nhưng nó không thành vấn đề với bất kỳ dự án lớn nào. Việc duy trì một dự án tách biệt cấu trúc và logic dễ dàng hơn nhiều so với dự án không.
  • Loại bỏ sự nhầm lẫn với tên sự kiện chính xác. Do sử dụng trình lắng nghe sự kiện nội tuyến hoặc gán trình lắng nghe sự kiện cho .oneventcác thuộc tính của các thành phần DOM, rất nhiều lập trình viên JavaScript thiếu kinh nghiệm nghĩ rằng tên sự kiện là ví dụ onclickhoặc onload. onkhông một phần của tên sự kiện . Tên sự kiện chính xác là clickload, và đó là cách tên sự kiện được truyền đến .addEventListener().
  • Hoạt động trong hầu hết tất cả các trình duyệt . Nếu bạn vẫn phải hỗ trợ IE <= 8, bạn có thể sử dụng polyfill từ MDN .

element.onevent = function() {}(ví dụ onclick, onload)

Mã ví dụ:

Đây là một cách để đăng ký trình xử lý sự kiện trong DOM 0. Hiện tại nó không được khuyến khích, bởi vì nó:

  • Cho phép bạn đăng ký chỉ một xử lý sự kiện. Ngoài ra, việc loại bỏ trình xử lý được gán không trực quan, vì để xóa trình xử lý sự kiện được gán bằng phương thức này, bạn phải hoàn nguyên thuộc oneventtính trở lại trạng thái ban đầu (nghĩa là null).
  • Không phản hồi lỗi một cách thích hợp. Ví dụ: nếu bạn nhầm, gán một chuỗi cho window.onload, ví dụ : window.onload = "test";, nó sẽ không gây ra bất kỳ lỗi nào. Mã của bạn sẽ không hoạt động và thật khó để tìm hiểu lý do tại sao. .addEventListener()tuy nhiên, sẽ đưa ra lỗi (ít nhất là trong Firefox): TypeError: Đối số 2 của EventTarget.addEventListener không phải là một đối tượng .
  • Không cung cấp cách chọn nếu bạn muốn xử lý sự kiện trong giai đoạn bắt hoặc sủi bọt.

Trình xử lý sự kiện nội tuyến ( oneventthuộc tính HTML)

Mã ví dụ:

Tương tự như vậy element.onevent, bây giờ nó không được khuyến khích. Bên cạnh những vấn đề element.oneventcó, nó:

  • Là một vấn đề bảo mật tiềm năng , bởi vì nó làm cho XSS có hại hơn nhiều. Ngày nay, các trang web nên gửi Content-Security-Policytiêu đề HTTP thích hợp để chặn các tập lệnh nội tuyến và chỉ cho phép các tập lệnh bên ngoài từ các miền đáng tin cậy. Xem Chính sách bảo mật nội dung hoạt động như thế nào?
  • Không tách rời cấu trúc tài liệu và logic .
  • Nếu bạn tạo trang của mình bằng tập lệnh phía máy chủ và ví dụ: bạn tạo một trăm liên kết, mỗi liên kết có cùng một trình xử lý sự kiện nội tuyến, mã của bạn sẽ dài hơn nhiều so với trình xử lý sự kiện chỉ được xác định một lần. Điều đó có nghĩa là khách hàng sẽ phải tải xuống nhiều nội dung hơn và kết quả là trang web của bạn sẽ chậm hơn.

Xem thêm


22

Mặc dù onclickhoạt động trong tất cả các trình duyệt, addEventListenernhưng không hoạt động trong các phiên bản Internet Explorer cũ hơn, sử dụng attachEventthay thế.

Nhược điểm của onclicknó là chỉ có thể có một trình xử lý sự kiện, trong khi hai cái còn lại sẽ kích hoạt tất cả các cuộc gọi lại đã đăng ký.


12

Theo tôi biết, sự kiện "tải" DOM ​​vẫn chỉ hoạt động rất hạn chế. Điều đó có nghĩa là nó sẽ chỉ bắn cho window object, images<script>các phần tử chẳng hạn. Việc onloadchuyển nhượng trực tiếp cũng vậy . Không có sự khác biệt kỹ thuật giữa hai. Có lẽ .onload =có một trình duyệt chéo tốt hơn.

Tuy nhiên, bạn không thể gán load eventcho một <div>hoặc <span>yếu tố hoặc có điều gì.


9

Tóm lược:

  1. addEventListenercó thể thêm nhiều sự kiện, trong khi với onclickđiều này không thể được thực hiện.
  2. onclickcó thể được thêm dưới dạng một HTMLthuộc tính, trong khi addEventListenerchỉ có thể được thêm vào trong <script>các phần tử.
  3. addEventListener có thể lấy một đối số thứ ba có thể dừng việc truyền bá sự kiện.

Cả hai có thể được sử dụng để xử lý các sự kiện. Tuy nhiên, addEventListenernên là lựa chọn ưu tiên vì nó có thể làm mọi thứ onclick và hơn thế nữa. Không sử dụng các onclickthuộc tính nội tuyến dưới dạng HTML vì điều này trộn lẫn javascript và HTML là một cách làm không tốt. Nó làm cho mã ít bảo trì hơn.


Và làm thế nào là mục tiêu của bạn chủ yếu được thực hiện? Ý tôi là, cá nhân tôi sẽ không sử dụng những người điều khiển nội tuyến onclickvì sợ bị cười nhạo trong phòng - nhưng thông thường các sự kiện bị ràng buộc theo những cách tồi tệ hơn và ít bảo trì hơn trong những năm gần đây. Các lớp như js-link, js-form-validationhoặc các thuộc tính dữ liệu data-jspackage="init"không có cách nào tốt hơn ... Và bạn thực sự sử dụng bong bóng sự kiện như thế nào? Cá nhân tôi rất thích có thể viết một trình xử lý mà không cần kiểm tra xem mục tiêu có thực sự phù hợp với yếu tố của tôi không - hoặc phải dừng truyền bá ở một số nơi do lỗi ngẫu nhiên.
Christoffer Bubach

3

Một chi tiết chưa được ghi nhận: các trình duyệt máy tính để bàn hiện đại coi các lần nhấn nút khác nhau là "nhấp chuột" AddEventListener('click'onclicktheo mặc định.

  • Trên Chrome 42 và IE11, cả hai onclickAddEventListenernhấp vào nhấp chuột trái và nhấp chuột giữa.
  • Trên Firefox 38, chỉonclick bắn khi nhấp chuột trái, nhưng nhấp vào bắn vào nhấp chuột trái, giữa phải.AddEventListener

Ngoài ra, hành vi nhấp chuột giữa rất không nhất quán trên các trình duyệt khi có liên quan đến con trỏ cuộn:

  • Trên Firefox, các sự kiện nhấp chuột giữa luôn luôn kích hoạt.
  • Trên Chrome, họ sẽ không kích hoạt nếu middleclick mở hoặc đóng con trỏ cuộn.
  • Trên IE, chúng kích hoạt khi con trỏ cuộn đóng, nhưng không chạy khi nó mở.

Cũng cần lưu ý rằng các sự kiện "nhấp chuột" cho bất kỳ phần tử HTML nào có thể chọn bằng bàn phím, chẳng hạn như inputbắn vào không gian hoặc nhập khi phần tử được chọn.


2

Javascript có xu hướng pha trộn mọi thứ vào các đối tượng và điều đó có thể khiến nó trở nên khó hiểu. Tất cả thành một là cách JavaScript.

Về cơ bản onclick là một thuộc tính HTML. Ngược lại, addEventListener là một phương thức trên đối tượng DOM đại diện cho một phần tử HTML.

Trong các đối tượng JavaScript, một phương thức chỉ là một thuộc tính có chức năng như một giá trị và hoạt động chống lại đối tượng mà nó được gắn vào (ví dụ sử dụng điều này).

Trong JavaScript, phần tử HTML được đại diện bởi DOM sẽ có các thuộc tính được ánh xạ lên các thuộc tính của nó.

Đây là nơi mọi người bị lẫn lộn vì JavaScript kết hợp mọi thứ vào một vùng chứa hoặc không gian tên duy nhất không có lớp cảm ứng.

Trong bố cục OO bình thường (ít nhất hợp nhất không gian tên của các thuộc tính / phương thức), bạn có thể có một cái gì đó như:

domElement.addEventListener // Object(Method)
domElement.attributes.onload // Object(Property(Object(Property(String))))

Có các biến thể như nó có thể sử dụng getter / setter cho onload hoặc HashMap cho các thuộc tính nhưng cuối cùng đó là giao diện của nó. JavaScript đã loại bỏ lớp cảm ứng đó với mong muốn biết những gì trong số những thứ khác. Nó hợp nhất domEuity và các thuộc tính với nhau.

Khả năng tương thích chặn bạn nên sử dụng addEventListener. Khi các câu trả lời khác nói về sự khác biệt trong vấn đề đó hơn là sự khác biệt cơ bản về lập trình, tôi sẽ từ bỏ nó. Về cơ bản, trong một thế giới lý tưởng, bạn thực sự chỉ có ý định sử dụng * từ HTML nhưng trong một thế giới thậm chí còn lý tưởng hơn, bạn không nên làm bất cứ điều gì như thế từ HTML.

Tại sao ngày nay nó chiếm ưu thế? Viết nhanh hơn, dễ học hơn và có xu hướng chỉ hoạt động.

Toàn bộ điểm của tải trong HTML là cấp quyền truy cập vào phương thức hoặc chức năng addEventListener ở vị trí đầu tiên. Bằng cách sử dụng nó trong JS, bạn sẽ trải qua HTML khi bạn có thể áp dụng nó trực tiếp.

Theo giả thuyết bạn có thể tạo các thuộc tính của riêng bạn:

$('[myclick]').each(function(i, v) {
     v.addEventListener('click', function() {
         eval(v.myclick); // eval($(v).attr('myclick'));
     });
});

Những gì JS làm với một chút khác biệt với điều đó.

Bạn có thể đánh đồng nó với một cái gì đó như (cho mọi yếu tố được tạo):

element.addEventListener('click', function() {
    switch(typeof element.onclick) {
          case 'string':eval(element.onclick);break;
          case 'function':element.onclick();break;
     }
});

Các chi tiết triển khai thực tế có thể sẽ khác nhau với một loạt các biến thể tinh tế làm cho hai biến thể hơi khác nhau trong một số trường hợp nhưng đó là ý chính của nó.

Có thể nói là một hack tương thích mà bạn có thể ghim một hàm vào một thuộc tính on vì các thuộc tính mặc định là tất cả các chuỗi.


2

Theo MDN , sự khác biệt như sau:

addEventListener:

Phương thức EventTarget.addEventListener () thêm đối tượng tương thích EventListener được chỉ định vào danh sách các trình lắng nghe sự kiện cho loại sự kiện đã chỉ định trên EventTarget mà nó được gọi. Mục tiêu sự kiện có thể là một Phần tử trong tài liệu, chính Tài liệu, Cửa sổ hoặc bất kỳ đối tượng nào khác hỗ trợ các sự kiện (chẳng hạn như XMLHttpRequest).

trong một cái nhấp chuột:

Thuộc tính onclick trả về mã xử lý sự kiện nhấp vào phần tử hiện tại. Khi sử dụng sự kiện nhấp để kích hoạt một hành động, cũng xem xét thêm hành động tương tự này vào sự kiện nhấn phím, để cho phép sử dụng hành động tương tự của những người không sử dụng chuột hoặc màn hình cảm ứng. Cú pháp phần tử.onclick = functionRef; trong đó functionRef là một hàm - thường là tên của hàm được khai báo ở nơi khác hoặc biểu thức hàm. Xem "Hướng dẫn JavaScript: Hàm" để biết chi tiết.

Ngoài ra còn có một sự khác biệt về cú pháp sử dụng như bạn thấy trong các mã dưới đây:

addEventListener:

// Function to change the content of t2
function modifyText() {
  var t2 = document.getElementById("t2");
  if (t2.firstChild.nodeValue == "three") {
    t2.firstChild.nodeValue = "two";
  } else {
    t2.firstChild.nodeValue = "three";
  }
}

// add event listener to table
var el = document.getElementById("outside");
el.addEventListener("click", modifyText, false);

trong một cái nhấp chuột:

function initElement() {
    var p = document.getElementById("foo");
    // NOTE: showAlert(); or showAlert(param); will NOT work here.
    // Must be a reference to a function name, not a function call.
    p.onclick = showAlert;
};

function showAlert(event) {
    alert("onclick Event detected!");
}

1

Nếu bạn không quá lo lắng về sự hỗ trợ của trình duyệt, có một cách để buộc lại tham chiếu 'cái này' trong chức năng được gọi bởi sự kiện. Nó thường sẽ trỏ đến phần tử tạo ra sự kiện khi hàm được thực thi, không phải lúc nào cũng là điều bạn muốn. Phần khó khăn là đồng thời có thể loại bỏ trình nghe sự kiện rất giống nhau, như trong ví dụ này: http://jsfiddle.net/roenbaeck/vBYu3/

/*
    Testing that the function returned from bind is rereferenceable, 
    such that it can be added and removed as an event listener.
*/
function MyImportantCalloutToYou(message, otherMessage) {
    // the following is necessary as calling bind again does 
    // not return the same function, so instead we replace the 
    // original function with the one bound to this instance
    this.swap = this.swap.bind(this); 
    this.element = document.createElement('div');
    this.element.addEventListener('click', this.swap, false);
    document.body.appendChild(this.element);
}
MyImportantCalloutToYou.prototype = {
    element: null,
    swap: function() {
        // now this function can be properly removed 
        this.element.removeEventListener('click', this.swap, false);           
    }
}

Đoạn mã trên hoạt động tốt trong Chrome và có thể có một số ý kiến ​​trái chiều về việc làm cho "liên kết" tương thích với các trình duyệt khác.


1

Sử dụng trình xử lý nội tuyến không tương thích với Chính sách bảo mật nội dung nên addEventListenercách tiếp cận an toàn hơn từ quan điểm đó. Tất nhiên, bạn có thể kích hoạt trình xử lý nội tuyến unsafe-inlinenhưng, như tên cho thấy, nó không an toàn vì nó mang lại toàn bộ các khai thác JavaScript mà CSP ngăn chặn.


1
Lưu ý: hạn chế bảo mật này chỉ áp dụng cho phát triển tiện ích mở rộng và các biện minh bảo mật được cung cấp trong tài liệu được liên kết phần lớn chỉ áp dụng cho phát triển tiện ích mở rộng trình duyệt. Tuy nhiên, một điểm được thực hiện trong tài liệu được liên kết cũng đúng với phát triển web là tách nội dung khỏi hành vi. Đó là thực hành tốt trên bảng.
Chris Baker

1

Cũng có thể mở rộng trình nghe bằng cách tạo mẫu cho nó (nếu chúng ta có tham chiếu đến nó và không phải là hàm ẩn danh) -hoặc thực hiện cuộc gọi 'onclick' đến thư viện hàm (một hàm gọi các hàm khác)

giống

    elm.onclick = myFunctionList
    function myFunctionList(){
      myFunc1();
      myFunc2();
    }

điều này có nghĩa là chúng ta không bao giờ phải thực hiện cuộc gọi onclick chỉ thay đổi chức năng myFunctionList () để làm những gì chúng ta muốn, nhưng điều này khiến chúng ta không kiểm soát được các pha sủi bọt / bắt bóng vì vậy nên tránh các trình duyệt mới hơn.

chỉ trong trường hợp ai đó tìm thấy chủ đề này trong tương lai ...


1

Element.onclick = function () {/ * làm công cụ * /}

Element.addEventListener ('click', function () {/ * làm công cụ * /}, false);

Họ dường như làm điều tương tự: lắng nghe sự kiện nhấp chuột và thực hiện chức năng gọi lại. Tuy nhiên, chúng không tương đương. Nếu bạn cần lựa chọn giữa hai thứ này, điều này có thể giúp bạn tìm ra cái nào là tốt nhất cho bạn.

Sự khác biệt chính là onclick chỉ là một thuộc tính và giống như tất cả các thuộc tính đối tượng, nếu bạn viết nhiều lần, nó sẽ bị ghi đè . Thay vào đó với addEventListener () , chúng ta có thể chỉ cần liên kết một trình xử lý sự kiện với phần tử và chúng ta có thể gọi nó mỗi khi chúng ta cần nó mà không phải lo lắng về bất kỳ thuộc tính ghi đè nào. Ví dụ được hiển thị ở đây,

Hãy dùng thử: https://jsfiddle.net/fjets5z4/5/

Ở nơi đầu tiên, tôi đã cố gắng tiếp tục sử dụng onclick, bởi vì nó ngắn hơn và trông đơn giản hơn và thực tế là như vậy. Nhưng tôi không khuyên bạn nên sử dụng nó nữa. Nó giống như sử dụng JavaScript nội tuyến. Sử dụng một cái gì đó như - đó là JavaScript nội tuyến - ngày nay rất được khuyến khích (CSS nội tuyến cũng không được khuyến khích, nhưng đó là một chủ đề khác).

Tuy nhiên, hàm addEventListener (), mặc dù là tiêu chuẩn, nhưng không hoạt động trong các trình duyệt cũ (Internet Explorer bên dưới phiên bản 9) và đây là một sự khác biệt lớn khác. Nếu bạn cần hỗ trợ các trình duyệt cổ này, bạn nên làm theo cách onclick. Nhưng bạn cũng có thể sử dụng jQuery (hoặc một trong những lựa chọn thay thế của nó): về cơ bản nó đơn giản hóa công việc của bạn và giảm sự khác biệt giữa các trình duyệt, do đó có thể giúp bạn tiết kiệm rất nhiều thời gian.

var clickEvent = document.getElementByID("onclick-eg");
var EventListener = document.getElementByID("addEventListener-eg");

clickEvent.onclick = function(){
    window.alert("1 is not called")
}
clickEvent.onclick = function(){
    window.alert("2 is not called")
}

EventListener.addEventListener("click",function(){
    window.alert("1 is called")
})
EventListener.addEventListener("click",function(){
    window.alert("2 is also called")
})

0

addEventListener cho phép bạn đặt nhiều trình xử lý, nhưng không được hỗ trợ trong IE8 hoặc thấp hơn.

IE có attachEvent, nhưng nó không hoàn toàn giống nhau.


0

Bối cảnh được tham chiếu bởi 'this'từ khóa trong JavasSript là khác nhau.

nhìn vào đoạn mã sau:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>

</head>
<body>
    <input id="btnSubmit" type="button" value="Submit" />
    <script>
        function disable() {
            this.disabled = true;
        }
        var btnSubmit = document.getElementById('btnSubmit');
        btnSubmit.onclick = disable();
        //btnSubmit.addEventListener('click', disable, false);
    </script>
</body>
</html>

Những gì nó làm là thực sự đơn giản. Khi bạn nhấp vào nút, nút sẽ tự động bị tắt.

Đầu tiên, khi bạn cố gắng kết nối các sự kiện theo cách button.onclick = function(), này, sự kiện onclick sẽ được kích hoạt bằng cách nhấp vào nút, tuy nhiên, nút sẽ không bị vô hiệu hóa do không có ràng buộc rõ ràng giữa trình xử lý sự kiện button.onclick và onclick. Nếu bạn gỡ lỗi nhìn thấy 'this'đối tượng, bạn có thể thấy nó đề cập đến 'window'đối tượng.

Thứ hai, nếu bạn bình luận btnSubmit.onclick = disable();và không chú ý, //btnSubmit.addEventListener('click', disable, false);bạn có thể thấy rằng nút bị vô hiệu hóa vì với cách này, có ràng buộc rõ ràng giữa sự kiện button.onclick và xử lý sự kiện onclick. Nếu bạn gỡ lỗi thành chức năng vô hiệu hóa, bạn có thể thấy 'this'đề cập đến button controlchứ không phải là window.

Đây là điều tôi không thích về JavaScript không nhất quán. Btw, nếu bạn đang sử dụng jQuery ( $('#btnSubmit').on('click', disable);), nó sử dụng ràng buộc rõ ràng.


8
Bạn cần phải viết btnSubmit.onclick = disable;(gán chức năng, không gọi nó). Sau đó, trong cả hai trường hợp thissẽ đề cập đến yếu tố nút.
Pasha

-1

onclick về cơ bản là một addEventListener thực hiện cụ thể một chức năng khi phần tử được nhấp. Vì vậy, hữu ích khi bạn có một nút thực hiện các thao tác đơn giản, như nút máy tính. addEventlistener có thể được sử dụng cho vô số thứ như thực hiện một thao tác khi DOM hoặc tất cả nội dung được tải, gần giống với window.onload nhưng có nhiều quyền kiểm soát hơn.

Lưu ý, Bạn thực sự có thể sử dụng nhiều hơn một sự kiện với nội tuyến hoặc ít nhất bằng cách sử dụng onclick bằng cách tách biệt từng chức năng với dấu chấm phẩy, như thế này ....

Tôi sẽ không viết một hàm với nội tuyến, vì bạn có thể có vấn đề sau này và nó sẽ là imo lộn xộn. Chỉ cần sử dụng nó để gọi các chức năng đã được thực hiện trong tệp tập lệnh của bạn.

Cái nào bạn sử dụng tôi cho rằng sẽ phụ thuộc vào những gì bạn muốn. addEventListener cho các hoạt động phức tạp và onclick cho đơn giản. Tôi đã thấy một số dự án không đính kèm một dự án cụ thể vào các yếu tố và thay vào đó sẽ triển khai một trình tạo sự kiện toàn cầu hơn để xác định xem một lần nhấn vào nút và thực hiện một số tác vụ nhất định tùy thuộc vào những gì được nhấn. Imo có khả năng có thể dẫn đến các vấn đề tôi nghĩ, và mặc dù nhỏ, có thể, lãng phí tài nguyên nếu người tổ chức sự kiện đó phải xử lý từng nhấp chuột

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.