nullのプロパティ 'addEventListener'を読み取れません


106

プロジェクトにはバニラJavaScriptを使用する必要があります。いくつかの機能がありますが、その1つはメニューを開くボタンです。ターゲットIDが存在するページでは機能しますが、IDが存在しないページではエラーが発生します。関数がIDを見つけられないページで、「nullのプロパティ 'addEventListener'を読み取れません」エラーが表示され、他の関数が機能しません。

以下は、メニューを開くボタンのコードです。

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

どうすればこれに対処できますか?このコードを別の関数ですべてラップするか、if / elseステートメントを使用して、特定のページのIDのみを検索するようにしますが、正確にはわかりません。


1
あなたはhtmlコードを表示できますか?id 'overlayBtn'の要素が見つからないようです
BlaShadow '29

2
関数がIDを見つけられないページで、「nullのプロパティ 'addEventListener'を読み取れません」エラーが表示され、他の関数が機能しません。答えはかなり問題だったと思います。要素が見つからなかったため、イベントリスナーを追加できません...
Etai

1
class代わりにhtml を使用してidgetElementByIdて、スクリプトでを呼び出す場合にのみ発生します。
Deke

回答:


196

最も簡単な方法はel、イベントリスナーを追加する前にnullでないことを確認することです。

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

驚くばかり。それはトリックをしました。また、onclick関数をそのifステートメントに移動しました。以下の最終コードを投稿しました。
morocklo 2014

3
それは次のようになりますnull前にマウントした成分を反応させます!

ありがとうございました:Dまさに私が探していたものです...私のアプリには複数のリスナーがあり、リスナーはさまざまなビューに分散しています。要素がページに存在する場合、それは私のJS
VegaStudiosを調整

とても便利です、ありがとう!
sc_props

113

document.getElementById('overlayBtn');戻ってきているようですnullDOMが完全に読み込まれる前に実行されるため。

このコード行を下に置くと

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

その後、問題なく実行されます。

例:

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

私も同じような状況に直面しました。これはおそらく、ページがロードされる前にスクリプトが実行されるためです。スクリプトをページの下部に配置することで、問題を回避しました。


1
ええ、シナリオに応じて、この問題には複数の解決策があると思います。
rpeg

16

同じエラーが発生しましたが、nullチェックを実行しても効果がなかったようです。

私が見つけた解決策は、DOMの読み込みがいつ完了したかを確認するために、ドキュメント全体のイベントリスナー内に関数をラップすることでした。

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

これは、HTMLクラスとIDを動的に変更するフレームワーク(Angular)を使用しているためだと思います。


1
Electronで遊ぶときにも同じ問題が発生します。同じ方法で保存しました。
チャールズ

9

JSがHTMLパーツの前に読み込まれるだけなので、その要素を見つけることができません。JSコード全体を、ウィンドウが読み込まれたときに呼び出される関数の中に置くだけです。

JavaScriptコードをHTMLの下に置くこともできます。


8

スクリプトは本文の前に読み込まれ、コンテンツの後にスクリプトを保持します


5

bodyタグの最後にスクリプトを置きます。

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

3

@Rob M.の協力に感謝します。コードの最終ブロックは次のようになります。

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

スクリプトタグに「async」を追加するだけで、問題が解決したようです。誰かが説明できれば、なぜかはわかりませんが、それでうまくいきました。私の推測では、ページはスクリプトの読み込みを待機していないため、JavaScriptと同時に読み込まれます。

Async / Awaitを使用すると、非同期コードを同期的に記述できます。これは、ジェネレーターとyieldステートメントを使用して実行を「一時停止」する構文上の砂糖であり、変数に割り当てる機能を提供します。

ここに参照リンクがあります -https : //medium.com/siliconwat/how-javascript-async-await-works-3cab4b7d21da


2

同じ問題が発生し、nullかどうかを確認しましたが、解決しませんでした。ページが読み込まれる前にスクリプトが読み込まれていたためです。したがって、スクリプトをend bodyタグの前に置くだけで問題が解決しました。


0

他の人が言ったように、問題はページ(特にターゲット要素)がロードされる前にスクリプトが実行されることです。

しかし、私はコンテンツを並べ替えるソリューションが好きではありません。

推奨される解決策は、onloadイベントのページにイベントハンドラーを配置し、そこにリスナーを設定することです。これにより、割り当てが実行される前にページとターゲット要素が読み込まれます。例えば

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

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

0

私は名前とともに引用のコレクションを持っています。特定の名前に関連付けられている最後の見積もりを更新するために更新ボタンを使用していますが、更新ボタンをクリックしても更新されません。server.jsファイルと外部jsファイル(main.js)のコードを以下に含めます。

main.js(外部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ファイル

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

すべてのページに感謝します。すべてのページではなく、使用する特定のページにスクリプトをロードします。swiper.jsまたは他のライブラリを使用する場合があるため、このエラーメッセージが表示される場合があります。この問題を解決して特定のページにJSライブラリをロードする唯一の方法です。そのIDが存在し、すべてのページで同じライブラリが読み込まれないようにします。

これがお役に立てば幸いです。


0

同じ問題がありましたが、IDが存在しました。そこで、「window.onload = init;」を追加してみました。次に、元のJSコードをinit関数でラップしました(必要なものを呼び出します)。これはうまくいったので、少なくとも私の場合は、ドキュメントが読み込まれる前にイベントリスナーを追加していました。これもあなたが経験していることかもしれません。


-1

これは、バンドルjsの実行時に要素がロードされていなかったためです。

をファイルの<script src="sample.js" type="text/javascript"></script>一番下に移動しindex.htmlます。このようにして、すべてのhtml要素が解析およびレンダリングされた後にスクリプトが確実に実行されるようにすることができます。


不正解です。これは古い学校の考え方です。先に述べたように、最後にロードするとロードが遅延しますが、DOMが完全に描画されるは限りません。DOMの描画がロードよりも遅いため、このハックを使用した古いページを実行できませんでした。この回答 により、実行前にDOMが確実に描画されます。
Machavity

-3

ウィンドウが読み込まれたときにすべてのイベントリスナーを追加します。スクリプトタグをどこに配置しても、魅力のように機能します。

window.addEventListener("load", startup);

function startup() {

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

}

myFunc(){}

ページの描画は、スクリプトの読み込みよりも時間がかかる場合があるため、すべての場合で位置はそれほど重要ではありません。リスナーを追加することをお勧めしますがload、同じ理由で廃止される予定です。DOMが完全に描画された後にのみ起動するため、DOMContentLoadedが推奨されます。
Machavity

ありがとうございます。Mozillaネットワークから回答を得ました。信頼できる情報源だと思いました。
Natalie Jimenez 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.