Satır içi Javascript (HTML'de) nasıl çalışır?


129

Bunun kötü bir uygulama olduğunu biliyorum. Mümkünse böyle kod yazmayın.

Elbette, kendimizi her zaman akıllı bir satır içi Javascript pasajının bir sorunu hızlı bir şekilde çözebileceği durumlarda bulacağız.

Böyle bir şey yazıldığında ne olduğunu (ve olası tuzakları) tam olarak anlamak için bu sorguyu takip ediyorum:

<a href="#" onclick="alert('Hi')">Click Me</a>

Anlayabildiğim kadarıyla bu işlevsel olarak aynı

<script type="text/javascript">
   $(function(){ // I use jQuery in this example
       document.getElementById('click_me').onclick = 
           function () { alert('Hi'); };
   });
</script>
<a href="#" id="click_me">Click Me</a>

Bundan çıkarım yaparak, özniteliğe atanan dizenin onclick, öğenin tıklama işleyicisine atanan anonim bir işlevin içine yerleştirildiği görülmektedir. Durum gerçekten bu mu?

Çünkü bunun gibi şeyler yapmaya başlıyorum:

<a href="#" onclick="$(this).next().fadeIn(); return false;">Display my next sibling</a> <!-- Return false in handler so as not to scroll to top of page! --> 

Hangisi çalışıyor. Ama bunun ne kadar bir hack olduğunu bilmiyorum. Şüpheli görünüyor çünkü geri döndürülen görünürde bir işlev yok!

Sorabilirsin, bunu neden yapıyorsun Steve? Satır içi JS kötü bir uygulamadır!

Dürüst olmak gerekirse, bir sayfanın bir bölümünü değiştirmek için kodun üç farklı bölümünü düzenlemekten yoruldum, özellikle de işe yarayıp yaramayacağını görmek için bir şeyin prototipini oluşturduğumda. Bu HTML öğesiyle özellikle ilgili kodun öğenin içinde tanımlanması çok daha kolaydır ve hatta bazen mantıklıdır : 2 dakika sonra bunun korkunç, berbat bir fikir olduğuna karar verdiğimde tüm div'i (veya her neyse ) ve sayfanın geri kalanında, oluşturma işlemini çok az yavaşlatan bir sürü gizemli JS ve CSS bozukluğum yok. Bu, referansın yerelliği kavramına benzer, ancak önbellek eksiklikleri yerine hatalara ve kod şişmesine bakıyoruz.


3
Haklısın, bu anonim bir işlev.
bhamlin

1
Sorguyu #click_meDOMready olayına bağlamanız veya komut dosyasını düğümden sonra yerleştirmeniz gerekir.
Bergi

1
Bir konsolda yap document.getElementById("click_me").onclick;. Ya da uyarın. Bunun bir işlevde olduğunu göreceksiniz.
D. Strout

Yanıtlar:


96

Neredeyse doğru anladınız, ancak thissatır içi koda sağlanan değeri hesaba katmadınız.

<a href="#" onclick="alert(this)">Click Me</a>

aslında şuna daha yakın:

<a href="#" id="click_me">Click Me</a>
<script type="text/javascript">
document.getElementById('click_me').addEventListener("click", function(event) {
    (function(event) {
        alert(this);
    }).call(document.getElementById('click_me'), event);
});
</script>

Satır içi olay işleyicileri this, olayın hedefine eşit olarak ayarlanır . Satır içi komut dosyasında anonim işlevi de kullanabilirsiniz

<a href="#" onclick="(function(){alert(this);})()">Click Me</a>

7
Komut dosyası etiketinden sonra gelmelidir, aksi takdirde etiket yürütüldüğünde mevcut değildir - cevabınızı bunu yansıtacak şekilde değiştirmenizi öneririm.
tanımsız

eventsatır içi ile nasıl yayılırım onclick='myFunction(event)'??
oldboy

9

Sahip olduğunuzda tarayıcı ne yapar?

<a onclick="alert('Hi');" ... >

"onclick" in gerçek değerini aşağıdaki gibi etkili bir şekilde ayarlamaktır:

new Function("event", "alert('Hi');");

Yani bir "olay" parametresi bekleyen bir işlev yaratır. (IE değil; daha çok basit ve anonim bir işlev gibi.)


2
Ah. Bu yüzden event, olayı (ve ondan gelen öğeyi event.target) satır içi JS snippet'imden almak için değişkeni gerçekten kullanabilirim ! Güzel.
Steven Lu

1
IE gerçekten eventparametreyi geçmez , ancak eventbu anonim işlevin içinde kullanırsanız, IE onu gerçek Etkinlik Nesnesi olarak anlayacaktır. Anonim işlev windowIE'de nesnenin bir özelliği olarak ayarlandığından , bunu olarak görecek window.event.
rdleal

8

Görünüşe göre Olay İşleyicisi Nitelikleri etrafında birçok kötü uygulama fırlatılıyor. Kötü uygulama, mevcut özellikleri en uygun olduğu yerde bilmemek ve kullanmaktır. Etkinlik Nitelikleri tamamen W3C Belgeli standartlardır ve bunlarla ilgili kötü bir uygulama yoktur. Satır içi stilleri yerleştirmekten farklı değildir, bu da W3C Belgeli ve zaman zaman yararlı olabilir. Senaryo etiketlerine sarılmış olsun ya da olmasın, aynı şekilde yorumlanacaktır.

https://www.w3.org/TR/html5/webappapis.html#event-handler-idl-attributes


2
Evet, hemfikir olmaya meyilliyim ve hatta bu tür bir satır içi kod kullanımının belirli durumlarda gerekçelendirilebileceğine dair makul "nedenler" bile sundum. Ancak gerçek şu ki, bir uygulama (web uygulaması veya başka türlü) belirli bir karmaşıklığa dönüştüğünde (ve bu genellikle çok fazla zaman veya çalışma gerektirmez) HTML düzeni hakkında dağınık küçük kod parçacıkları olması muhtemeldir. sürdürülebilirlik açısından mimari açıdan sağlam olmayacaktır. Örneğin, bir HTML dosyası içinde JS'yi doğrudan kodlamaya başlayarak bile, spagettifikasyonun kaygan eğimi cazip hale geliyor.
Steven Lu

1
Ve bu benim de hemfikir olduğum bir aleyhine uygun ve geçerli bir argüman. Normalde satır içi komut dosyası veya bu materyal için stil eklemiyorum. Ama insanların farklı zevkleri var. Örneğin çoğu, gövde bölümüne komut dosyası ve stil etiketleri eklemeyi sever, buna dayanamıyorum. Ama geçerli ve bazı insanlar bundan hoşlanıyor. bad practice/spaghettificationBazıları için dikişler , good practice/structurediğerleri içindir.
Daniel B

Github.com/styled-components/styled-components adresine bakıyordum ve örneğin bunu react ile birleştirirseniz, artık uygulamanızın aslında birlikte yaşayan (umarım barışçıl bir şekilde) bir bileşeniyle ilişkili her şeye tek bir yerde sahibiz. Ve aslında korkunç da görünmüyor. İlerleme gibi geliyor. Bu açıdan bakıldığında, satır içi stilleri ve kodu HTML'ye karıştırmak doğru yol değildir (şimdiye kadar HTML ve stillerin JS koduna sıkışması gibi görünüyor).
Steven Lu

5

Sorunuzu yanıtlamanın en iyi yolu, onu eylem halinde görmektir .

<a id="test" onclick="alert('test')"> test </a> 

Js içinde

var test = document.getElementById('test');
console.log( test.onclick ); 

Gördüğünüz gibi console, Chrome kullanıyorsanız, IE'de biraz farklı olsa da, içeri giren olay nesnesi ile anonim bir işlev yazdırır.

function onclick(event) {
   alert('test')
}

Satır içi olay işleyicileri hakkındaki bazı noktalarınıza katılıyorum. Evet, yazmaları kolay, ancak kodu birden fazla yerde değiştirmek zorunda olduğunuza katılmıyorum, kodunuzu iyi yapılandırırsanız, bunu yapmanız gerekmez.


Sanırım böyle bir şey <button onclick="login()"> test login </button>prototipleme için gayet iyi. Şu anda kullanıcı etkileşimi gerektiren bir şeyi test etmek istiyorsunuz ve daha sonra yine de sileceksiniz. Neden her yere fazladan kod yazasınız?
Dagg Nabbit

Ekstra kod değil, sadece ekstra anonim bir işlev. Ve her yerde değil, aslında hepsi tek bir yerde, komut dosyası etiketlerinde.
aziz punjani

Aynı "kodunuzu iyi yapılandırma" fikrini paylaştığımızdan emin değilim. Kullanıcı arayüzünü, temel işlevlerinizin gerçekte yaşadığı yerde "temel işlevlerinize" bağlarsanız, bu bana onları kullanıcı arabiriminde bağlamaktan daha kötü bir eşleştirme düzenlemesi gibi görünüyor. Genelde tüm kullanıcı arayüzü bağlama öğelerini temel şeylerden ayrı
tutuyorum

3

Şüpheli görünüyor çünkü geri döndürülen görünürde bir işlev yok!

Nesnenin tıklama olayına eklenen anonim bir işlevdir.

Bunu neden yapıyorsun Steve?

Neden böyle yapıyorsun ..... Ah boşver, bahsettiğin gibi, gerçekten kötü bir uygulama yaygın olarak benimseniyor :)


3

Bunu konsolda deneyin:

var div = document.createElement('div');

div.setAttribute('onclick', 'alert(event)');

div.onclick

Chrome'da şunu gösterir:

function onclick(event) {
  alert(event)
}

... ve standart dışı namemalıdır div.onclickDİR "onclick".

Bu nedenle, bunun anonim olup olmadığı "anonim" tanımınıza bağlıdır. Boş dizge var foo = new Function()nerede foo.nameolduğu gibi bir şeyle karşılaştırın ve şöyle bir foo.toString()şey üretecektir:

function anonymous() {

}

Bu, Pointy'nin cevabına bir yorum olarak başladı, ancak gerçekten bir yorum olarak işe yaramadı. Sanırım buradaki en iyi cevap onunki.
Dagg Nabbit
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.