2014-09-29 140 views
44

我必須對項目使用vanilla JavaScript。我有幾個功能,其中一個是打開菜單的按鈕。它在存在目標標識的頁面上工作,但在id不存在的頁面上導致錯誤。在那些功能找不到id的頁面上,我收到一個「Can not read property'addEventListener'null」的錯誤,而我的其他功能都沒有工作。無法讀取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 2014-09-29 19:14:41

+1

在那些功能找不到id的頁面上,我收到「Can not read property'addEventListener'null」錯誤,而我的其他功能都沒有工作。 我認爲這個問題的答案非常多。你找不到元素,所以你不能添加一個事件監聽器... – Etai 2014-09-29 19:16:16

+1

它可以簡單地發生,如果你已經在你的html中使用'class'而不是'id',並且你調用'getElementById'在您的腳本中。 – Deke 2016-06-25 19:50:38

回答

89

我認爲最簡單的方法是隻檢查el不添加事件監聽前空:

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

真棒。那就是訣竅。我還將onclick函數移到了if語句中。我發佈了下面的最終代碼。 – morocklo 2014-09-29 19:26:13

+1

在反應組件掛載之前,它將是'null'! – 2017-09-12 08:36:41

2

感謝@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; 
    }; 
} 
11

我得到了同樣的錯誤,但執行空檢查似乎沒有幫助。

我發現的解決方案是將我的函數封裝在整個文檔的事件偵聽器中,以檢查DOM何時完成加載。

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

我認爲這是因爲我正在使用改變我的HTML類和ID的動態框架(Angular)。

10

我面臨類似的情況。這可能是因爲該腳本在頁面加載之前執行。通過將腳本放在頁面底部,我繞過了這個問題。

+1

是的,我認爲這個問題有多種解決方案取決於場景。 – rpeg 2016-04-18 21:02:16

0

正如其他人所說的問題是,該腳本是在加載頁面(特別是目標元素)之前執行的。

但我不喜歡重新排序內容的解決方案。

首選的解決方案是在頁面onload事件上放置一個事件處理函數,並在那裏設置Listener。這將確保頁面和目標元素在執行賦值之前加載。例如

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

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

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

}) 
-1

這是因爲元件並未在時刻正在執行的束JS時加載。

我會將<script src="sample.js" type="text/javascript"></script>移動到index.html文件的最底部。這樣你可以確保腳本在所有html元素被分析和渲染後執行。

+0

不正確。這是老派的想法。正如你所說的那樣,加載結束會延遲加載,但它不能確保DOM完全繪製**。由於DOM繪製速度比加載速度慢,因此使用此黑客的較舊頁面無法運行。 [這個答案](https://stackoverflow.com/a/30063375/2370483)**確保** DOM在執行前被繪製。 – Machavity 2017-12-30 16:29:03

-2

當窗口加載時,添加所有事件偵聽器。無論您將腳本標記放在哪裏,都可以像魅力一樣工作。

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

頁面的繪製有時會比腳本的加載花費更長的時間,所以在所有情況下,位置都不是那麼重要。添加一個監聽器是首選方式,但'load'也出於同樣的原因被棄用。 [DOMContentLoaded](https://stackoverflow.com/questions/2414750/difference-between-domcontentloaded-and-load-events)是首選的方式,因爲它僅在DOM完全繪製後觸發。 – Machavity 2017-12-30 16:35:27

+0

這是一個很好的嘗試,你。 – statosdotcom 2017-12-30 16:43:56

+0

謝謝,我會嘗試。我從Mozilla網絡得到了我的答案。我認爲這是一個可信賴的來源。 – 2017-12-30 16:50:55