Null değerinin 'addEventListener' özelliği okunamıyor


108

Bir proje için vanilya JavaScript kullanmam gerekiyor. Birkaç işlevim var, bunlardan biri menü açan bir düğme. Hedef kimliğinin bulunduğu sayfalarda çalışır, ancak kimliğin olmadığı sayfalarda bir hataya neden olur. İşlevin kimliği bulamadığı sayfalarda, "'addEventListener' özelliği null okunamıyor" hatası alıyorum ve diğer işlevlerimden hiçbiri çalışmıyor.

Menüyü açan düğmenin kodu aşağıdadır.

function swapper() {
toggleClass(document.getElementById('overlay'), 'open');
}

var el = document.getElementById('overlayBtn');
el.addEventListener('click', swapper, false);

var text = document.getElementById('overlayBtn');
text.onclick = function(){
this.innerHTML = (this.innerHTML === "Menu") ? "Close" : "Menu";
return false;
};

Bununla nasıl başa çıkacağım? Muhtemelen bu kodu başka bir işleve sarmam veya if / else deyimini kullanmam gerekiyor, böylece yalnızca belirli sayfalarda kimliği arar, ancak tam olarak emin olamaz.


1
html kodunu gösterebilir misin? Görünüşe göre 'overlayBtn' kimliğine sahip öğe bulunamıyor
BlaShadow

2
İşlevin kimliği bulamadığı sayfalarda, "'addEventListener' özelliği null okunamıyor" hatası alıyorum ve diğer işlevlerimden hiçbiri çalışmıyor. Sanırım cevabın büyük ölçüde sorunun içinde olduğunu düşünüyorum. Öğeyi bulamadığınız için ona bir olay dinleyicisi ekleyemezsiniz ...
Etai

1
Bunun classyerine html'nizi kullandıysanız idve getElementByIdkomut dosyalarınızda a için çağırırsanız bu basitçe gerçekleşebilir .
Deke

Sadece benzer bir sorunla karşı karşıya kaldı addEventListener could be null. Etiketten <script src="..."></script>sonra hareket <body/>etmek bu sorunu çözüyor gibi görünüyor.
Reborn

Yanıtlar:


202

Bence en kolay yaklaşım, elbir olay dinleyicisi eklemeden önce boş olmadığını kontrol etmektir:

var el = document.getElementById('overlayBtn');
if(el){
  el.addEventListener('click', swapper, false);
}

harika. bu hile yaptı. Ayrıca onclick işlevini bu if ifadesine taşıdım. Son kodu aşağıya gönderdim.
morocklo

3
nulltepki bileşeni monte edilmeden önce olacak !

Teşekkürler dostum: D Tam olarak aradığım şey .... Uygulamamda birden fazla dinleyicim var ve dinleyiciler farklı görünümlere dağılmış durumda. Öğe sayfada mevcutsa, JS
VegaStudios

113

Bu , DOM tam olarak yüklenmeden önce çalıştırıldığı document.getElementById('overlayBtn');için geri dönüyor gibi görünüyor null.

Bu kod satırını altına koyarsanız

window.onload=function(){
  -- put your code here
}

o zaman sorunsuz çalışacaktır.

Misal:

window.onload=function(){
    var mb = document.getElementById("b");
    mb.addEventListener("click", handler);
    mb.addEventListener("click", handler2);
}


function handler() {
    $("p").html("<br>" + $("p").text() + "<br>You clicked me-1!<br>");
}

function handler2() {
    $("p").html("<br>" + $("p").text() + "<br>You clicked me-2!<br>");
}

23

Benzer bir durumla karşılaştım. Bunun nedeni muhtemelen komut dosyasının sayfa yüklenmeden önce yürütülmesidir. Komut dosyasını sayfanın altına yerleştirerek sorunu çözdüm.


1
Evet, senaryoya bağlı olarak bu sorunun birden fazla çözümü olduğunu düşünüyorum.
rpeg

16

Aynı hatayı alıyordum, ancak boş bir kontrol yapmak yardımcı olmadı.

Bulduğum çözüm, DOM'un yüklemeyi ne zaman bitirdiğini kontrol etmek için işlevimi tüm belge için bir olay dinleyicisinin içine yerleştirmekti.

document.addEventListener('DOMContentLoaded', function () {
    el.addEventListener('click', swapper, false);
});

Bunun nedeni HTML sınıflarımı ve ID'leri dinamik olarak değiştiren bir çerçeve (Angular) kullanmamdan kaynaklanıyor.


1
Electron ile oynarken de aynı problemle karşılaşıyorum. Aynı yöntemi kullanarak kaydetti.
charles

9

Sadece JS'nizin HTML bölümünden önce yüklenmesi bcz ve bu nedenle o öğeyi bulamıyor. Tüm JS kodunuzu, pencere yüklendiğinde çağrılacak bir işlevin içine koyun.

Javascript kodunuzu html'nin altına da koyabilirsiniz.


8

komut dosyası gövdeden önce yükleniyor, komut dosyasını içerikten sonra tut


6

Komut dosyasını gövde etiketinin sonuna yerleştirin.

<html>
    <body>
        .........
        <script src="main.js"></script>
    </body>
</html>

3

@ Rob M.'ye yardımı için teşekkürler. Son kod bloğu şuna benziyordu:

function swapper() {
  toggleClass(document.getElementById('overlay'), 'open');
}

var el = document.getElementById('overlayBtn');
if (el){
  el.addEventListener('click', swapper, false);

  var text = document.getElementById('overlayBtn');
  text.onclick = function(){
    this.innerHTML = (this.innerHTML === "Menu") ? "Close" : "Menu";
    return false;
  };
}

2

Sorunu çözmüş gibi görünen komut dosyası etiketime 'eşzamansız' ekledim. Birisi açıklayabilirse neden emin değilim, ama benim için çalıştı. Tahminimce sayfa komut dosyasının yüklenmesini beklemiyor, dolayısıyla sayfa JavaScript ile aynı anda yükleniyor.

Async / Await, senkronize bir şekilde asenkron kod yazmamızı sağlar. bu sadece üreteçleri kullanan sözdizimsel şekerdir ve yürütmeyi "duraklatmak" için ifadeler üretir, bize onu bir değişkene atama yeteneği verir!

İşte referans bağlantısı- https://medium.com/siliconwat/how-javascript-async-await-works-3cab4b7d21da


2

Aynı sorunla karşılaştım ve boşluğu kontrol ettim ama yardımcı olmadı. Çünkü komut dosyası, sayfa yüklenmeden önce yükleniyordu. Yani komut dosyasını son gövde etiketinin önüne yerleştirmek sorunu çözdü.


0

Başkalarının da söylediği gibi, kodun sayfa (ve özellikle hedef eleman) yüklenmeden önce yürütülmesidir.

Ancak içeriği yeniden düzenleme çözümünü sevmiyorum.

Tercih edilen çözüm, sayfa yükleme olayına bir olay işleyicisi koymak ve Dinleyiciyi oraya ayarlamaktır. Bu, atama yapılmadan önce sayfanın ve hedef öğenin yüklenmesini sağlayacaktır. Örneğin

    <script>
    function onLoadFunct(){
            // set Listener here, also using suggested test for null
    }
    ....
    </script>

    <body onload="onLoadFunct()" ....>
    .....

0

İsimlerle birlikte bir alıntı koleksiyonum var. Belirli bir adla ilişkili son teklifi güncellemek için güncelleme düğmesini kullanıyorum, ancak güncelle düğmesine tıklandığında güncellenmiyor. Server.js dosyası ve harici js dosyası (main.js) için aşağıdaki kodu ekliyorum.

main.js (harici js)

var update = document.getElementById('update');
if (update){
update.addEventListener('click', function () {

  fetch('quotes', {
  method: 'put',
  headers: {'Content-Type': 'application/json'},
  body: JSON.stringify({
    'name': 'Muskan',
    'quote': 'I find your lack of faith disturbing.'
  })
})var update = document.getElementById('update');
if (update){
update.addEventListener('click', function () {

  fetch('quotes', {
  method: 'put',
  headers: {'Content-Type': 'application/json'},
  body: JSON.stringify({
    'name': 'Muskan',
    'quote': 'I find your lack of faith disturbing.'
  })
})
.then(res =>{
    if(res.ok) return res.json()
})
.then(data =>{
    console.log(data);
    window.location.reload(true);
})
})
}

server.js dosyası

app.put('/quotes', (req, res) => {
  db.collection('quotations').findOneAndUpdate({name: 'Vikas'},{
    $set:{
        name: req.body.name,
        quote: req.body.quote
    }
  },{
    sort: {_id: -1},
    upsert: true
  },(err, result) =>{
    if (err) return res.send(err);
    res.send(result);
  })

})

0

Hepsinden teşekkürler, Komut Dosyalarını tüm sayfalar için değil, kullandığınız belirli sayfalara yükleyin, bazen swiper.js veya başka bir kitaplık kullanarak bu hata mesajına neden olabilir, bu sorunu çözmenin tek yolu JS kitaplığını belirli sayfalara yüklemektir. bu kimlik var ve aynı kitaplığın tüm sayfalarda yüklenmesini engelliyor.

Umarım bu size yardımcı olur.


0

Aynı problemi yaşadım ama kimliğim vardı. Bu yüzden "window.onload = init;" eklemeyi denedim Daha sonra orijinal JS kodumu bir init işlevi ile sardım (ne isterseniz onu arayın). Bu işe yaradı, en azından benim durumumda, belgem yüklenmeden önce bir olay dinleyicisi ekliyordum. Sizin de deneyimlediğiniz şey bu olabilir.


-1

Bunun nedeni, js paketi yürütülürken öğenin yüklenmemiş olmasıdır.

Ben hareket ediyorum <script src="sample.js" type="text/javascript"></script>çok altında olacak şekilde index.htmldosyaya. Bu şekilde, tüm html öğeleri ayrıştırılıp oluşturulduktan sonra betiğin çalıştırılmasını sağlayabilirsiniz.


Yanlış. Bu eski okul düşüncesi. Sonunda yükleme, belirttiğiniz gibi yüklemeyi geciktirir, ancak DOM'un tam olarak çekildiğini garanti etmez . Bu saldırıyı kullanan daha eski sayfalarım çalışmıyordu çünkü DOM çekilişi yüklemeden daha yavaştı. Bu cevap , DOM'un yürütülmeden önce çizilmesini sağlar .
Machavity

-3

Bir pencere yüklendiğinde tüm olay dinleyicilerini ekleyin. Komut dosyası etiketlerini nereye koyarsanız koyun bir tılsım gibi çalışır.

window.addEventListener("load", startup);

function startup() {

  document.getElementById("el").addEventListener("click", myFunc);
  document.getElementById("el2").addEventListener("input", myFunc);

}

myFunc(){}

Sayfanın çizimi bazen komut dosyasının yüklenmesinden daha uzun sürebilir, bu nedenle konum her durumda o kadar önemli değildir. Dinleyici eklemek tercih edilen yoldur, ancak loadaynı nedenle kullanımdan kaldırılmıştır. DOMContentLoaded , yalnızca DOM tamamen çizildikten sonra tetiklendiği için tercih edilen yoldur.
Machavity

Teşekkürler deneyeceğim. Cevabımı Mozilla ağından aldım. Güvenilir bir kaynak olduğunu düşündüm.
Natalie Jimenez
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.