2014-09-29 147 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