Pertanyaan addEventListener vs onclick


Apa perbedaannya addEventListener dan onclick?

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

Kode di atas berada bersama dalam file .js terpisah, dan keduanya berfungsi dengan sempurna.


511
2018-06-14 18:49


asal


Jawaban:


Keduanya benar, tetapi tidak satupun dari mereka "terbaik" per se, dan mungkin ada alasan pengembang memilih untuk menggunakan kedua pendekatan.

Event Listeners (addEventListener dan attachEvent IE)

Versi sebelumnya dari Internet Explorer menerapkan javascript berbeda dari hampir semua peramban lainnya. Dengan versi kurang dari 9, Anda menggunakan attachEvent[dokter] metode, seperti ini:

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

Di sebagian besar peramban lain (termasuk IE 9 dan di atasnya), Anda menggunakan addEventListener[dokter], seperti ini:

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

Menggunakan pendekatan ini (DOM Level 2 acara), Anda dapat melampirkan jumlah kejadian yang tidak terbatas secara teoritis ke suatu elemen tunggal. Satu-satunya batasan praktis adalah memori sisi klien dan masalah kinerja lainnya, yang berbeda untuk setiap browser.

Contoh di atas mewakili penggunaan fungsi anonim [dokter]. Anda juga dapat menambahkan listener kejadian menggunakan referensi fungsi [dokter] atau penutupan [dokter]:

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

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

Fitur penting lainnya dari addEventListener adalah parameter terakhir, yang mengontrol bagaimana pendengar bereaksi terhadap peristiwa yang menggelegak [dokter]. Saya telah melewatkan salah dalam contoh, yang merupakan standar untuk kemungkinan 95% kasus penggunaan. Tidak ada argumen yang setara untuk attachEvent, atau saat menggunakan kejadian inline.

Peristiwa inline (HTML onclick = "" properti dan element.onclick)

Di semua browser yang mendukung javascript, Anda dapat menempatkan listener kejadian sebaris, yang berarti tepat di kode HTML. Anda mungkin pernah melihat ini:

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

Sebagian besar pengembang yang berpengalaman menghindari metode ini, tetapi ini menyelesaikan pekerjaan; itu sederhana dan langsung. Anda tidak dapat menggunakan penutupan atau fungsi anonim di sini (meskipun handler itu sendiri merupakan fungsi anonim), dan kendali ruang lingkup Anda terbatas.

Metode lain yang Anda sebutkan:

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

... adalah setara dengan javascript sebaris kecuali bahwa Anda memiliki kontrol lebih dari ruang lingkup (karena Anda menulis skrip daripada HTML) dan dapat menggunakan fungsi anonim, referensi fungsi, dan / atau penutupan.

Kelemahan signifikan dengan kejadian inline adalah bahwa tidak seperti pendengar acara yang dijelaskan di atas, Anda mungkin hanya memiliki satu acara inline yang ditetapkan. Peristiwa inline disimpan sebagai atribut / properti dari elemen [dokter], artinya dapat ditimpa.

Menggunakan contoh <a> dari HTML di atas:

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

... ketika Anda mengklik elemen, Anda akan hanya lihat "Apakah hal # 2" - Anda overwrote yang pertama ditugaskan dari onclick properti dengan nilai kedua, dan Anda overwrote inline HTML asli onclick properti juga. Lihat disini: http://jsfiddle.net/jpgah/.

Mana yang Terbaik?

Pertanyaannya adalah masalah kompatibilitas dan kebutuhan browser. Apakah Anda saat ini perlu melampirkan lebih dari satu peristiwa ke elemen? Maukah kamu di masa depan? Mustahil, Anda akan. attachEvent dan addEventListener diperlukan. Jika tidak, acara inline akan melakukan trik.

jQuery dan framework javascript lainnya mengenkapsulasi implementasi browser yang berbeda dari kejadian level 2 DOM dalam model generik sehingga Anda dapat menulis kode yang sesuai lintas-browser tanpa harus khawatir tentang sejarah IE sebagai seorang pemberontak. Kode yang sama dengan jQuery, semua lintas-browser dan siap untuk di-rock:

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

Jangan kehabisan dan dapatkan kerangka hanya untuk satu hal ini. Anda dapat dengan mudah menggulirkan utilitas kecil Anda untuk mengurus browser yang lebih lama:

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!'); }
);

Cobalah: http://jsfiddle.net/bmArj/

Mempertimbangkan semua itu, kecuali skrip yang Anda cari membawa perbedaan browser ke dalam akun dengan cara lain (dalam kode tidak ditampilkan dalam pertanyaan Anda), bagian yang menggunakan addEventListener tidak akan berfungsi di versi IE kurang dari 9.

Dokumentasi dan Bacaan Terkait


733
2018-06-14 18:59



Perbedaan yang Anda bisa lihat jika Anda memiliki beberapa fungsi lain:

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

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

Fungsi 2, 3, dan 4 berfungsi, tetapi 1 tidak. Hal ini karena addEventListener tidak menimpa penangan kejadian yang ada, sedangkan onclick menimpa semua yang ada onclick = fn penangan event.

Perbedaan signifikan lainnya, tentu saja, adalah itu onclick akan selalu bekerja, sedangkan addEventListener tidak berfungsi di Internet Explorer sebelum versi 9. Anda dapat menggunakan analog attachEvent (yang memiliki sedikit sintaks yang berbeda) di IE <9.


131
2018-06-14 18:52



Dalam jawaban ini saya akan menjelaskan tiga metode mendefinisikan penangan event DOM.

element.addEventListener()

Contoh kode:

const element = document.querySelector('a');
element.addEventListener('click', event => event.preventDefault(), true);
<a href="//google.com">Try clicking this link.</a>

element.addEventListener() memiliki banyak keuntungan:

  • Memungkinkan Anda mendaftar tak terbatas penangan kejadian dan menghapusnya dengan element.removeEventListener().
  • Has useCapture parameter, yang menunjukkan apakah Anda ingin menangani acara di dalamnya menangkap atau menggelembung fase. Lihat: Tidak dapat memahami atribut useCapture di addEventListener.
  • Peduli tentang semantik. Pada dasarnya, itu membuat pengurusan acara pendaftaran lebih eksplisit. Untuk pemula, panggilan fungsi membuatnya jelas itu sesuatu terjadi, sedangkan menugaskan acara ke beberapa properti elemen DOM setidaknya tidak intuitif.
  • Memungkinkan Anda struktur dokumen terpisah (HTML) dan logika (JavaScript). Dalam aplikasi web kecil mungkin tidak menjadi masalah, tetapi itu tidak masalah dengan proyek yang lebih besar. Ini jauh lebih mudah untuk mempertahankan proyek yang memisahkan struktur dan logika daripada proyek yang tidak.
  • Hilangkan kebingungan dengan nama acara yang benar. Karena menggunakan pendengar acara inline atau menugaskan pendengar acara .onevent properti elemen DOM, banyak programer JavaScript yang tidak berpengalaman menganggap bahwa nama acara adalah contohnya onclick atau onload. on aku s tidak bagian dari nama acara. Nama acara yang benar adalah click dan load, dan begitulah nama acara diteruskan .addEventListener().
  • Bekerja di hampir semua browser. Jika Anda masih harus mendukung IE <= 8, Anda dapat menggunakan polyfill dari MDN.

element.onevent = function() {} (misalnya. onclick, onload)

Contoh kode:

const element = document.querySelector('a');
element.onclick = event => event.preventDefault();
<a href="//google.com">Try clicking this link.</a>

Ini adalah cara untuk mendaftarkan penangan kejadian di DOM 0. Sekarang tidak disarankan, karena:

  • Memungkinkan Anda mendaftar hanya satu pengendali event. Juga menghapus handler yang ditetapkan tidak intuitif, karena untuk menghapus event handler yang ditugaskan menggunakan metode ini, Anda harus kembali onevent properti kembali ke keadaan awalnya (mis. null).
  • Tidak menanggapi kesalahan dengan tepat. Misalnya, jika Anda salah menetapkan string ke window.onload, sebagai contoh: window.onload = "test";, itu tidak akan membuang kesalahan. Kode Anda tidak akan berfungsi dan akan sangat sulit untuk mencari tahu alasannya. .addEventListener() namun, akan menimbulkan kesalahan (setidaknya di Firefox): TypeError: Argument 2 dari EventTarget.addEventListener bukan objek.
  • Tidak menyediakan cara untuk memilih apakah Anda ingin menangani acara dalam fase menangkap atau menggelegak.

Penangan event inline (onevent Atribut HTML)

Contoh kode:

<a href="//google.com" onclick="event.preventDefault();">Try clicking this link.</a>

Demikian pula untuk element.onevent, sekarang tidak disarankan. Selain masalah itu element.onevent memiliki, itu:

  • Adalah masalah keamanan potensial, karena itu membuat XSS jauh lebih berbahaya. Saat ini situs web harus dikirim dengan semestinya Content-Security-Policy Header HTTP untuk memblokir skrip sebaris dan mengizinkan skrip eksternal hanya dari domain tepercaya. Lihat Bagaimana cara kerja Kebijakan Keamanan Konten?
  • Tidak struktur dokumen dan logika terpisah.
  • Jika Anda menghasilkan halaman Anda dengan skrip sisi server, dan misalnya Anda menghasilkan seratus tautan, masing-masing dengan pengendali kejadian inline yang sama, kode Anda akan jauh lebih lama daripada jika pengendali event didefinisikan hanya sekali. Itu berarti klien harus mengunduh lebih banyak konten, dan hasilnya situs web Anda akan lebih lambat.

Lihat juga


43
2018-01-29 21:01



Sementara onclick berfungsi di semua browser, addEventListener tidak berfungsi di Internet Explorer versi lama, yang menggunakan attachEvent sebagai gantinya.

Kelemahan dari onclick adalah hanya ada satu pengelola acara, sementara dua lainnya akan memecat semua panggilan terdaftar.


16
2018-06-14 18:52



Sejauh yang saya tahu, "beban" acara DOM masih hanya bekerja sangat terbatas. Itu berarti hanya akan menyala untuk window object, images dan <script> elemen misalnya. Hal yang sama berlaku untuk yang langsung onload tugas. Tidak ada perbedaan teknis antara keduanya. Mungkin .onload = memiliki availabilty lintas-browser yang lebih baik.

Namun, Anda tidak dapat menetapkan load event ke a <div> atau <span> elemen atau yang lainnya.


12
2017-08-01 17:27



Jika Anda tidak terlalu khawatir tentang dukungan browser, ada cara untuk mengulang referensi 'ini' dalam fungsi yang disebut oleh acara tersebut. Ini biasanya akan menunjuk ke elemen yang menghasilkan peristiwa ketika fungsi dijalankan, yang tidak selalu seperti yang Anda inginkan. Bagian yang sulit adalah pada saat yang sama dapat menghapus listener kejadian yang sama, seperti yang ditunjukkan dalam contoh ini: 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);           
    }
}

Kode di atas berfungsi dengan baik di Chrome, dan mungkin ada beberapa shim yang membuat "ikatan" kompatibel dengan browser lain.


1
2018-03-14 09:36



Menggunakan penangan inline tidak kompatibel dengan Kebijakan Keamanan Konten sehingga addEventListener pendekatan lebih aman dari sudut pandang itu. Tentu saja Anda dapat mengaktifkan penangan inline dengan unsafe-inline tetapi, seperti namanya, itu tidak aman karena membawa kembali seluruh gerombolan eksploit JavaScript yang mencegah CSP.


1
2018-04-20 16:40



Satu detail belum diketahui: peramban desktop modern menganggap penekanan tombol berbeda sebagai "klik" AddEventListener('click' dan onclick secara default.

  • Di Chrome 42 dan IE11, keduanya onclick dan AddEventListener klik tembak di klik kiri dan tengah.
  • Di Firefox 38, onclick kebakaran hanya di klik kiri, tapi AddEventListener klik api di kiri, tengah dan klik kanan.

Juga, perilaku klik tengah adalah sangat tidak konsisten di seluruh browser ketika kursor gulir terlibat:

  • Di Firefox, aktivitas klik-tengah selalu aktif.
  • Di Chrome, mereka tidak akan diaktifkan jika middleclick membuka atau menutup kursor gulir.
  • Pada IE, mereka memecat saat kursor gulir tertutup, tetapi tidak ketika terbuka.

Juga perlu dicatat bahwa peristiwa "klik" untuk elemen HTML yang dapat dipilih melalui keyboard seperti input juga aktifkan ruang atau masuk saat elemen dipilih.


1
2018-06-30 19:30



Juga dimungkinkan untuk memperpanjang pendengar dengan membuat prototipe (jika kita memiliki referensi untuk itu dan itu bukan fungsi anonim) -atau membuat 'onclick' panggilan panggilan ke fungsi perpustakaan (fungsi memanggil fungsi lain)

seperti

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

ini berarti kita tidak perlu untuk mem-chenge onclick call hanya mengubah function myFunctionList () untuk melakukan apa yang kita inginkan, tetapi ini meninggalkan kita tanpa mengontrol fase penggembungan / penangkapan jadi harus dihindari untuk browser yang lebih baru.

untuk berjaga-jaga jika seseorang menemukan utas ini di masa mendatang ...


1
2017-07-25 20:49



Menurut MDN, perbedaannya adalah seperti di bawah ini:

addEventListener:

Metode EventTarget.addEventListener () menambahkan yang ditentukan   EventListener-kompatibel objek ke daftar pendengar acara untuk   ditentukan jenis acara pada EventTarget yang disebut. Itu   target acara dapat berupa Unsur dalam dokumen, Dokumen itu sendiri, a   Jendela, atau objek lain yang mendukung acara (seperti   XMLHttpRequest).

onclick:

Properti onclick mengembalikan kode event handler klik pada   elemen saat ini. Saat menggunakan peristiwa klik untuk memicu tindakan, juga   pertimbangkan untuk menambahkan tindakan yang sama ini ke acara keydown, untuk mengizinkan   penggunaan tindakan yang sama oleh orang-orang yang tidak menggunakan mouse atau sentuhan   layar. Syntax element.onclick = functionRef; dimana functionRef adalah a   fungsi - sering kali nama fungsi dinyatakan di tempat lain atau fungsi   ekspresi. Lihat "Panduan JavaScript: Fungsi" untuk detailnya.

Ada juga perbedaan sintaks dalam penggunaan seperti yang Anda lihat dalam kode di bawah ini:

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);

onclick:

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
2018-04-27 03:41



addEventListener memungkinkan Anda mengatur beberapa penangan, tetapi tidak didukung di IE8 atau lebih rendah.

IE punya attachEvent, tapi tidak persis sama.


0
2018-06-14 18:52