2014-09-29 14 views
44

Muszę użyć wanilii JavaScript dla projektu. Mam kilka funkcji, z których jedną jest przycisk otwierający menu. Działa na stronach, na których istnieje identyfikator docelowy, ale powoduje błąd na stronach, na których identyfikator nie istnieje. Na stronach, na których funkcja nie może znaleźć identyfikatora, pojawia się komunikat "Nie można odczytać właściwości" addEventListener "o wartości" null "i żadna z moich innych funkcji nie działa.Nie można odczytać właściwości 'addEventListener' o wartości zerowej

Poniżej znajduje się kod przycisku otwierającego menu.

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

Jak sobie z tym poradzić? Prawdopodobnie będę musiał zawinąć ten kod w inną funkcję lub użyć instrukcji if/else, aby wyszukiwał on tylko identyfikator na określonych stronach, ale nie był do końca pewny.

+1

Czy możesz pokazać kod HTML. wydaje się, że nie można znaleźć elementu o identyfikatorze 'overlayBtn' – BlaShadow

+1

Na stronach, na których funkcja nie może znaleźć identyfikatora, pojawia się komunikat "Nie można odczytać właściwości" addEventListener 'o wartości null "i żadna z moich innych funkcji nie działa. Myślę, że odpowiedź na to pytanie była prawie w ogóle. Nie możesz znaleźć elementu, więc nie możesz dodać detektora zdarzeń do niego ... – Etai

+1

Może się tak zdarzyć, jeśli użyłeś 'class' w swoim html zamiast' id' i wołasz o 'getElementById' w twoich skryptach. – Deke

Odpowiedz

89

Myślę, że najprostszym rozwiązaniem byłoby po prostu sprawdzić, czy nie jest null el Przed dodaniem detektor zdarzeń:

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

niesamowite. to wystarczyło. Przeniosłem także funkcję onclick do tej instrukcji if. Poniżej zamieściłem ostatni kod. – morocklo

+1

będzie "null" przed zamontowaniem komponentu reagującego! –

2

Dzięki @Rob M. za pomoc. Tak wyglądał końcowy blok kodu:

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; 
    }; 
} 
11

Otrzymałem ten sam błąd, ale wykonanie zerowej kontroli nie wydawało się pomóc.

Rozwiązaniem, które znalazłem, było objęcie funkcji wewnątrz detektora zdarzeń dla całego dokumentu w celu sprawdzenia, kiedy DOM zakończył ładowanie.

Myślę, że to dlatego, że używam szkieletu (kątowego), który dynamicznie zmienia moje klasy HTML i identyfikatory.

10

Zmierzyłem się z podobną sytuacją. Jest tak prawdopodobnie dlatego, że skrypt jest wykonywany przed załadowaniem strony. Umieszczając skrypt u dołu strony, omijam problem.

+1

Tak, myślę, że istnieje wiele rozwiązań tego problemu w zależności od scenariusza. – rpeg

0

Jak powiedzieli inni, problem polega na tym, że skrypt jest wykonywany przed załadowaniem strony (w szczególności elementu docelowego).

Ale nie podoba mi się rozwiązanie zmiany kolejności treści.

Preferowane rozwiązanie polega na umieszczeniu obsługi zdarzeń na stronie zdarzenia onload i ustawieniu tam Listenera. Zapewni to załadowanie strony i elementu docelowego przed wykonaniem przypisania. np

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

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

Wydaje się, że document.getElementById('overlayBtn'); wraca null ponieważ wykonuje przed DOM pełnego obciążenia.

Jeśli umieścisz ten wiersz kodu pod

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

to będzie działać bez problemu.

Przykład:

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>"); 
} 
0

Mam kolekcję cytatów wraz z nazwami. Używam przycisku aktualizacji, aby zaktualizować ostatnią wycenę związaną z określoną nazwą, ale po kliknięciu przycisku aktualizacji nie aktualizuje się. Załączam poniższy kod dla pliku server.js i zewnętrznego pliku js (main.js).

main.js (kd zewnętrzne)

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

plików server.js

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

}) 
-1

Jest tak, ponieważ element ten nie został załadowany w czasie, gdy wiązka js był wykonywany.

Przeniesię <script src="sample.js" type="text/javascript"></script> na samo dno pliku index.html. W ten sposób można zagwarantować, że skrypt zostanie wykonany po przeanalizowaniu i renderowaniu wszystkich elementów HTML.

+0

Niepoprawnie. To jest myślenie w starym stylu. Ładowanie na końcu opóźnia ładowanie, jak stwierdzono, ale ** nie zapewnia, że ​​DOM jest w pełni narysowany **. Miałem starsze strony, które wykorzystywały ten hack, nie działały, ponieważ losowanie DOM było wolniejsze niż ładunek. [Ta odpowiedź] (https://stackoverflow.com/a/30063375/2370483) ** zapewnia ** DOM jest rysowany przed wykonaniem. – Machavity

-2

Dodaj wszystkie detektory zdarzeń, gdy ładowane są okna. Działa jak urok, niezależnie od tego, gdzie umieszczasz znaczniki skryptu.

window.addEventListener("load", startup); 
function startup() { 
document.getElementById("el").addEventListener("click", myFunc); 
document.getElementById("el2").addEventListener("input", myFunc); 
} 
myFunc(){ 
} 
+0

Rysowanie strony może czasami trwać dłużej niż ładowanie skryptu, więc pozycja nie jest tak ważna we wszystkich przypadkach. Dodanie detektora jest preferowanym sposobem, ale 'load' jest również przestarzałe z tego samego powodu. [DOMContentLoaded] (https://stackoverflow.com/questions/2414750/difference-between-domcontentloaded-and-load-events) jest preferowanym sposobem, ponieważ uruchamia się dopiero po pełnym rysowaniu modelu DOM. – Machavity

+0

To była bardzo dobra próba, ty. – statosdotcom

+0

Dzięki temu spróbuję. Dostałem odpowiedź z sieci Mozilli. Myślałem, że to jest zaufane źródło. –

Powiązane problemy