Saya telah mendengar berkali-kali bahwa menggunakan peristiwa JavaScript, seperti onClick()
, dalam HTML adalah praktik yang buruk, karena itu tidak baik untuk semantik. Saya ingin tahu apa kerugiannya dan bagaimana cara memperbaiki kode berikut?
<a href="#" onclick="popup('/map/', 300, 300, 'map'); return false;">link</a>
javascript
html
NiLL
sumber
sumber
#
, siapa pun yang memilih untuk menonaktifkan javascript akan mandek dan tidak dapat melakukan apa pun. Untuk beberapa situs itu adalah hal yang baik, tetapi hanya dengan membuka jendela, itu benar-benar bodoh untuk tidak memberikan tautan "nyata".<button>
, karena tautan seharusnya mengarah ke sumber daya yang sebenarnya. Itu lebih semantik seperti itu dan lebih jelas untuk pengguna pembaca layar.Jawaban:
Anda mungkin berbicara tentang Javascript yang tidak mencolok , yang akan terlihat seperti ini:
dengan logika di file javascript pusat terlihat seperti ini:
Keuntungannya adalah
sumber
onClick
. Anda juga dapat menulis unit test jika Anda ingin melawan skrip Anda yang juga sangat sulit saya asumsikan jika kode berada di dalamonClick
dan tidak ada logika yang dipisahkan. Saya pribadi tidak memiliki masalah men-debug JavaScript yang tidak mengganggu dan manfaat dalam mengelola dan menguji kode JavaScript adalah jauh dari bagus untuk tidak menggunakannya.onclick
dapat secara lebih eksplisit memetakan hubungan sebab akibat antara interaksi elemen dan efek (pemanggilan fungsi) serta mengurangi beban kognitif. Banyak pelajaran yang melempar peserta didik ke dalamaddEventListener
paket ide yang lebih banyak di dalam sintaksis yang lebih sulit. Selanjutnya, kerangka kerja berbasis komponen baru-baru ini seperti Riot dan Bereaksi menggunakanonclick
atribut dan mengubah gagasan tentang apa yang seharusnya menjadi pemisahan. Mentransfer dari HTMLonclick
ke komponen yang mendukung ini mungkin merupakan proses "langkah" yang lebih efektif untuk belajar.Jika Anda menggunakan jQuery maka:
HTML:
JS:
Ini memiliki manfaat tetap bekerja tanpa JS, atau jika pengguna mengklik tautan tersebut.
Ini juga berarti bahwa saya dapat menangani sembulan umum dengan menulis ulang lagi ke:
HTML:
JS:
Ini akan memungkinkan Anda menambahkan sembulan ke tautan apa pun dengan hanya memberikannya kelas sembulan.
Gagasan ini dapat diperluas lebih jauh seperti:
HTML:
JS:
Sekarang saya dapat menggunakan sedikit kode yang sama untuk banyak popup di seluruh situs saya tanpa harus menulis banyak hal onclick! Yay untuk dapat digunakan kembali!
Ini juga berarti bahwa jika nanti saya memutuskan bahwa popup adalah praktik yang buruk, (yang memang demikian!) Dan saya ingin menggantinya dengan jendela modal gaya lightbox, saya dapat mengubah:
untuk
dan semua popup saya di seluruh situs saya sekarang bekerja dengan sangat berbeda. Saya bahkan bisa melakukan deteksi fitur untuk memutuskan apa yang harus dilakukan pada sembulan, atau menyimpan preferensi pengguna untuk mengizinkannya atau tidak. Dengan onclick inline, ini membutuhkan salinan dan upaya menempel yang sangat besar.
sumber
Dengan aplikasi JavaScript yang sangat besar, pemrogram menggunakan lebih banyak enkapsulasi kode untuk menghindari polusi lingkup global. Dan untuk membuat fungsi tersedia untuk aksi onClick dalam elemen HTML, itu harus dalam lingkup global.
Anda mungkin telah melihat file JS yang terlihat seperti ini ...
Ini adalah Ekspresi Fungsi Segera Diminta (IIFE) dan fungsi apa pun yang dinyatakan di dalamnya hanya akan ada dalam lingkup internal mereka.
Jika Anda mendeklarasikan
function doSomething(){}
dalam IIFE, lalu membuatdoSomething()
aksi onClick suatu elemen di halaman HTML Anda, Anda akan mendapatkan kesalahan.Sebaliknya, jika Anda membuat eventListener untuk elemen itu dalam IIFE itu dan menelepon
doSomething()
ketika pendengar mendeteksi acara klik, Anda baik karena pendengar dandoSomething()
berbagi ruang lingkup IIFE.Untuk aplikasi web kecil dengan jumlah kode minimal, tidak masalah. Tetapi jika Anda bercita-cita untuk menulis basis kode yang besar dan dapat dipelihara,
onclick=""
adalah kebiasaan yang harus Anda hindari.sumber
Ini tidak baik karena beberapa alasan:
eval
Hal paling sederhana adalah menambahkan
name
atribut ke<a>
elemen Anda , maka Anda bisa melakukannya:meskipun praktik terbaik modern adalah menggunakan
id
alih - alih nama, dan menggunakanaddEventListener()
alih-alih menggunakanonclick
karena itu memungkinkan Anda untuk mengikat beberapa fungsi ke satu peristiwa.sumber
addEventListener()
, dan mengapa.Ada beberapa alasan:
Saya merasa bantu untuk memisahkan markup, yaitu skrip HTML dan sisi klien. Misalnya, jQuery memudahkan untuk menambahkan penangan acara secara terprogram.
Contoh yang Anda berikan akan rusak di agen pengguna apa pun yang tidak mendukung javascript, atau javascript dimatikan. Konsep peningkatan progresif akan mendorong hyperlink sederhana
/map/
untuk agen pengguna tanpa javascript, kemudian menambahkan penangan klik prgramatis untuk agen pengguna yang mendukung javascript.Sebagai contoh:
Markup:
Javascript:
sumber
<a href="https://stackoverflow.com/map/" onclick="popup('/map/', 300, 300, 'map'); return false;">link</a>
Revisi
Pendekatan JavaScript yang tidak mencolok baik di MASA LALU - terutama event handler binding dalam HTML dianggap sebagai praktik buruk (terutama karena
onclick events run in the global scope and may cause unexpected error
apa yang disebutkan oleh YiddishNinja )Namun...
Saat ini tampaknya pendekatan ini agak ketinggalan jaman dan perlu beberapa pembaruan. Jika seseorang ingin menjadi pengembang frontend profesional dan menulis aplikasi yang besar dan rumit maka dia harus menggunakan kerangka kerja seperti Angular, Vue.js, dll. Namun kerangka itu biasanya menggunakan (atau memungkinkan untuk menggunakan) template-HTML di mana penangan acara terikat dalam kode html-template secara langsung dan ini sangat berguna, jelas dan efektif - misalnya dalam template sudut biasanya orang menulis:
Dalam js / html mentah, ini setara dengan
Perbedaannya adalah bahwa dalam
onclick
peristiwa js mentah dijalankan dalam lingkup global - tetapi kerangka kerja menyediakan enkapsulasi.Jadi di mana masalahnya?
Masalahnya adalah ketika programmer pemula yang selalu mendengar bahwa html-onclick buruk dan yang selalu menggunakan
btn.addEventListener("onclick", ... )
ingin menggunakan beberapa kerangka kerja dengan template (addEventListener
juga memiliki kelemahan - jika kita memperbarui DOM secara dinamis menggunakaninnerHTML=
(yang cukup cepat ) - maka kita kehilangan acara penangan mengikat dengan cara itu). Kemudian dia akan menghadapi sesuatu seperti kebiasaan buruk atau pendekatan yang salah untuk penggunaan kerangka kerja - dan dia akan menggunakan kerangka kerja dengan cara yang sangat buruk - karena dia akan fokus terutama pada bagian js dan tidak pada bagian kerangka (dan menghasilkan tidak jelas dan sulit untuk mempertahankan kode). Untuk mengubah kebiasaan ini, ia akan kehilangan banyak waktu (dan mungkin ia akan membutuhkan keberuntungan dan guru).Jadi menurut saya, berdasarkan pengalaman dengan siswa saya, lebih baik bagi mereka jika mereka menggunakan html-handler-bind di awal. Seperti yang saya katakan memang benar bahwa penangan dipanggil dalam lingkup global tetapi pada tahap ini siswa biasanya membuat aplikasi kecil yang mudah dikendalikan. Untuk menulis aplikasi yang lebih besar, mereka memilih beberapa kerangka kerja.
Jadi apa yang harus dilakukan?
Kita dapat MEMPERBARUI pendekatan JavaScript yang Tidak Mengganggu dan mengizinkan pengikat acara bind (akhirnya dengan parameter sederhana) dalam html (tetapi hanya pengikat ikatan - tidak memasukkan logika ke dalam klik seperti pada pertanyaan OP). Jadi menurut saya di js / html mentah ini harus diizinkan
atau
Tampilkan cuplikan kode
Tetapi contoh di bawah ini TIDAK boleh diizinkan
Kenyataannya berubah, sudut pandang kita juga harus
sumber
addEventListener
. Iklan 2. Ya mereka bisa ditimpa (namun biasanya tidak ada yang melakukannya) - di mana masalahnya? Iklan 3. Handler tidak akan dipecat setelah menghapus attrib onclick - buktikan di siniIni adalah paradigma
baru yangdisebut " JavaScript Tidak Mengganggu ". "Standar web" saat ini mengatakan untuk memisahkan fungsi dan presentasi.Ini sebenarnya bukan "praktik buruk", hanya saja sebagian besar standar baru ingin Anda menggunakan pendengar acara alih-alih menggunakan JavaScript.
Juga, ini mungkin hanya hal pribadi, tapi saya pikir ini jauh lebih mudah dibaca ketika Anda menggunakan pendengar acara, terutama jika Anda memiliki lebih dari 1 pernyataan JavaScript yang ingin Anda jalankan.
sumber
Pertanyaan Anda akan memicu diskusi saya kira. Gagasan umumnya adalah memisahkan perilaku dan struktur itu baik. Selanjutnya, afaik, penangan klik sebaris harus
eval
diarahkan untuk 'menjadi' fungsi javascript nyata. Dan itu cukup kuno, meskipun itu argumen yang cukup goyah. Ah, baca beberapa tentangnya @ quirksmode.orgsumber
kinerja dan efisiensi.
sumber
Dua alasan lagi untuk tidak menggunakan penangan inline:
Mereka dapat meminta kutipan yang lolos dari masalah
Diberikan string sewenang - wenang , jika Anda ingin dapat membangun inline handler yang memanggil fungsi dengan string itu, untuk solusi umum, Anda harus melarikan diri dari pembatas atribut (dengan entitas HTML terkait), dan Anda akan harus lolos dari pembatas yang digunakan untuk string di dalam atribut, seperti berikut:
Itu sangat jelek. Dari contoh di atas, jika Anda tidak mengganti
'
s, SyntaxError akan menghasilkan, karenaalert('foo'"bar')
bukan sintaks yang valid. Jika Anda tidak mengganti"
s, maka peramban akan menafsirkannya sebagai akhironclick
atribut (dibatasi dengan"
s di atas), yang juga akan salah.Jika seseorang terbiasa menggunakan penangan inline, ia harus memastikan untuk mengingat melakukan sesuatu yang mirip dengan yang di atas (dan melakukannya dengan benar ) setiap kali , yang membosankan dan sulit untuk dipahami dalam sekejap. Lebih baik untuk menghindari penangan inline sepenuhnya sehingga string sewenang-wenang dapat digunakan dalam penutupan sederhana:
Bukankah itu jauh lebih baik?
Rantai lingkup penangan inline sangat aneh
Menurut Anda apa yang akan dicatat oleh kode berikut?
Cobalah, jalankan cuplikannya. Mungkin bukan itu yang Anda harapkan. Mengapa itu menghasilkan apa yang dilakukannya? Karena penangan inline dijalankan di dalam
with
blok. Kode di atas ada di dalam tigawith
blok: satu untukdocument
, satu untuk<form>
, dan satu untuk<button>
:Tampilkan cuplikan kode
Karena
disabled
merupakan properti tombol, referensidisabled
di dalam inline handler mengacu pada properti tombol, bukandisabled
variabel luar . Ini cukup kontra-intuitif.with
memiliki banyak masalah: ini dapat menjadi sumber bug yang membingungkan dan secara signifikan memperlambat kode. Bahkan tidak diizinkan sama sekali dalam mode ketat. Tetapi dengan penangan inline, Anda dipaksa untuk menjalankan kode melaluiwith
s - dan bukan hanya melalui satuwith
, tetapi melalui beberapawith
s bersarang . Ini gila.with
tidak boleh digunakan dalam kode. Karena penangan inline secara implisit memerlukanwith
bersama dengan semua perilakunya yang membingungkan, penangan inline harus dihindari juga.sumber