ไม่สามารถอ่านคุณสมบัติ 'addEventListener' ของ null


108

ฉันต้องใช้วานิลลา JavaScript สำหรับโปรเจ็กต์ ฉันมีฟังก์ชั่นบางอย่างซึ่งหนึ่งในนั้นคือปุ่มที่เปิดเมนู ทำงานบนหน้าที่มีรหัสเป้าหมาย แต่ทำให้เกิดข้อผิดพลาดบนหน้าที่ไม่มีรหัส ในหน้าเหล่านั้นที่ฟังก์ชันไม่พบ id ฉันได้รับข้อผิดพลาด "ไม่สามารถอ่านคุณสมบัติ 'addEventListener' ของ null" และฟังก์ชันอื่น ๆ ของฉันไม่ทำงาน

ด้านล่างนี้คือรหัสสำหรับปุ่มที่เปิดเมนู

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

2
ในหน้าเหล่านั้นที่ฟังก์ชันไม่พบ id ฉันได้รับข้อผิดพลาด "ไม่สามารถอ่านคุณสมบัติ 'addEventListener' ของ null" และฟังก์ชันอื่น ๆ ของฉันไม่ทำงาน ฉันคิดว่าคำตอบนั้นค่อนข้างน่าสนใจในคำถาม คุณไม่พบองค์ประกอบดังนั้นคุณจึงไม่สามารถเพิ่มตัวฟังเหตุการณ์เข้าไปได้ ...
Etai

1
มันสามารถเกิดขึ้นได้หากคุณใช้classใน html ของคุณแทนที่จะเป็นidและคุณเรียกหาgetElementByIdในสคริปต์ของคุณ
Deke

addEventListener could be nullต้องเผชิญกับปัญหาที่คล้ายกันเพียงที่ การย้าย<script src="..."></script>หลัง<body/>แท็กดูเหมือนจะช่วยแก้ปัญหานี้ได้
เกิด

คำตอบ:


202

ฉันคิดว่าวิธีที่ง่ายที่สุดelคือตรวจสอบว่าไม่เป็นโมฆะก่อนที่จะเพิ่มตัวฟังเหตุการณ์:

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

น่ากลัว นั่นเป็นเคล็ดลับ ฉันยังย้ายฟังก์ชัน onclick ไปไว้ในคำสั่ง if ฉันโพสต์รหัสสุดท้ายด้านล่าง
morocklo

3
มันจะเป็นnullก่อนที่ส่วนประกอบของปฏิกิริยาจะเมานต์!

ขอบคุณผู้ชาย: D สิ่งที่ฉันกำลังมองหาคืออะไร .... ฉันมีผู้ฟังหลายคนในแอปของฉันและผู้ฟังก็กระจายออกไปในมุมมองที่แตกต่างกัน หากองค์ประกอบนั้นมีอยู่ในหน้าแสดงว่ามันกำลัง
ยุ่งเหยิง

113

ดูเหมือนว่าdocument.getElementById('overlayBtn');จะกลับมาnullเพราะดำเนินการก่อนที่ DOM จะโหลดเต็มที่

หากคุณใส่รหัสบรรทัดนี้ไว้ใต้

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

ฉันได้รับข้อผิดพลาดเดียวกัน แต่การตรวจสอบค่าว่างดูเหมือนจะไม่ช่วยอะไร

วิธีแก้ปัญหาที่ฉันพบคือการรวมฟังก์ชันของฉันไว้ในตัวฟังเหตุการณ์สำหรับเอกสารทั้งหมดเพื่อตรวจสอบเมื่อ DOM โหลดเสร็จ

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

ฉันคิดว่านี่เป็นเพราะฉันใช้เฟรมเวิร์ก (เชิงมุม) ที่เปลี่ยนคลาส HTML และ ID ของฉันแบบไดนามิก


1
ฉันพบปัญหาเดียวกันเมื่อเล่นกับ Electron บันทึกโดยใช้วิธีการเดียวกัน
charles

9

มันเป็นเพียง bcz JS ของคุณถูกโหลดก่อนส่วน HTML ดังนั้นจึงไม่พบองค์ประกอบนั้น เพียงใส่รหัส JS ทั้งหมดของคุณในฟังก์ชันซึ่งจะถูกเรียกใช้เมื่อโหลดหน้าต่าง

คุณยังสามารถใส่โค้ด Javascript ของคุณไว้ด้านล่าง html



6

ใส่สคริปต์ที่ท้ายแท็กเนื้อหา

<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 ช่วยให้เราสามารถเขียนโค้ดอะซิงโครนัสในรูปแบบซิงโครนัสได้ มันเป็นเพียงแค่น้ำตาลวากยสัมพันธ์โดยใช้เครื่องกำเนิดไฟฟ้าและให้คำสั่งเพื่อ "หยุด" การดำเนินการทำให้เราสามารถกำหนดให้กับตัวแปรได้!

นี่คือลิงค์อ้างอิง - https://medium.com/siliconwat/how-javascript-async-await-works-3cab4b7d21da


2

ฉันพบปัญหาเดียวกันและตรวจสอบค่าว่าง แต่ไม่ได้ช่วย เนื่องจากสคริปต์กำลังโหลดก่อนโหลดหน้า ดังนั้นเพียงแค่วางสคริปต์ก่อนแท็ก end body ก็จะแก้ปัญหาได้


0

ดังที่คนอื่น ๆ กล่าวว่าปัญหาคือสคริปต์ถูกดำเนินการก่อนที่เพจ (และโดยเฉพาะอย่างยิ่งองค์ประกอบเป้าหมาย) จะถูกโหลด

แต่ฉันไม่ชอบวิธีแก้ปัญหาในการจัดลำดับเนื้อหาใหม่

วิธีแก้ปัญหาที่ต้องการคือการวางตัวจัดการเหตุการณ์บนหน้าเหตุการณ์ onload และตั้งค่า Listener ที่นั่น เพื่อให้แน่ใจว่าเพจและองค์ประกอบเป้าหมายถูกโหลดก่อนที่จะดำเนินการมอบหมาย เช่น

    <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ก็เลิกใช้ด้วยเหตุผลเดียวกัน DOMContentLoadedเป็นวิธีที่ต้องการเนื่องจากจะเริ่มทำงานหลังจาก DOM ถูกดึงจนสุดเท่านั้น
Machavity

ขอบคุณฉันจะพยายาม ฉันได้รับคำตอบจากเครือข่าย Mozilla ฉันคิดว่ามันเป็นแหล่งที่เชื่อถือได้
Natalie Jimenez
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.