开发者问题收集

未捕获的类型错误:无法读取 null 的属性 addEventListener

2019-11-14
14566

我正在为我的 javascript 课程做作业,但一直出现错误

fetch_page.js:109 Uncaught TypeError: Cannot read property 'addEventListener' of null at addEventListeners (fetch_page.js:109) at fetch_page.js:121

老实说,我完全不懂 javascript,但我被迫选修这门课程以获得网络管理学位。有人能指出我在哪里犯了这个错误吗?

window.addEventListener('DOMContentLoaded', (function() {
  var contents;

  var protocol;
  var hostname;
  var directory;
  var file;

  function parseBase() {
    var pos, slashPos;
    var remainder;

    pos = BASE.indexOf('://');
    protocol = BASE.substr(0, pos);
    remainder = BASE.substr(pos + 3);
    slashPos = remainder.indexOf('/');
    if (slashPos === -1) {
      hostname = remainder;
      directory = "";
      file = "";
    } else {
      hostname = remainder.substr(0, slashPos);
      remainder = remainder.substr(slashPos + 1);
      slashPos = remainder.lastIndexOf('/');
      if (slashPos === -1) {
        directory = "";
        file = remainder;
      } else {
        directory = remainder.substr(0, slashPos);
        file = remainder.substr(slashPos + 1);
      }
    }
    console.log("protocol:", protocol);
    console.log("hostname:", hostname);
    console.log("directory:", directory);
    console.log("file:", file);
  }

  function relativeToAbsolute(url) {
    if (url.indexOf('://') > -1) { // http://somedomain.com/path/file.html
      return url;
    } else if (url[0] === '/') { // /path/file.html
      return protocol + "://" + hostname + url;
    } else { // path/file.html
      if (directory === "") {
        return protocol + "://" + hostname + "/" + url;
      } else {
        return protocol + "://" + hostname + "/" + directory + "/" + url;
      }
    }
  }

  function parsePage() {
    var parser = new DOMParser();
    contents = parser.parseFromString(atob(PAGE), "text/html");
    console.log(contents);
  }

  function moveChildren(source, destination) {
    while (source.childNodes.length > 0) {
      var child = source.childNodes[0];
      source.removeChild(child);
      destination.appendChild(child);
    }
  }

  function fixTags(tagName, attribute) {
    var tags = contents.getElementsByTagName(tagName);

    for (var counter = 0; counter < tags.length; counter++) {
      var url = tags[counter].getAttribute(attribute);
      if (url) {
        tags[counter].setAttribute(attribute, relativeToAbsolute(url));
      }
    }
  }

  function fixRedirectedTags(tagName, attribute) {
    var tags = contents.getElementsByTagName(tagName);

    for (var counter = 0; counter < tags.length; counter++) {
      var url = tags[counter].getAttribute(attribute);
      if (url) {
        tags[counter].setAttribute(attribute,
          window.location.origin + window.location.pathname + '?url=' + encodeURIComponent(relativeToAbsolute(url)));

      }
    }
  }

  function fixURLs() {
    fixTags('img', 'src');
    fixTags('script', 'src');
    fixTags('link', 'href');
    fixRedirectedTags('a', 'href');
  }

  function moveContent() {
    moveChildren(contents.head, document.head);
    moveChildren(contents.body, document.getElementById('contents'));
  }

  function submit() {
    console.log("submitted:", encodeURIComponent(document.getElementById('urlBox').value));
  }

  function addEventListeners() {
    document.getElementById('goButton').addEventListener('click', submit);
    document.getElementById('urlBox').addEventListener('keydown', function(event) {
      if (event.keyCode == 13 || event.keyCode == 10) {
        submit();
      }
    });
  }

  return function() {
    parseBase();
    parsePage();
    fixURLs();
    moveContent();
    addEventListeners();
  }
})())
body {
	margin: 0px;
}
#searchBox {
	background: black;
	color: white;
	width: 100%;
	text-align: center;
	vertical-align: middle;
	padding: 10px;
	}
#goButton {
	background: red;
	color: black;
	padding: 4px
	font-weight: bold;
	font-family: Arial;
	font-size: .75em;
	vertical-align: middle;
	cursor: pointer;
}
#urlBox {
	width: 50%
}
#contents {
	border: 1px solid black;
}
<?php
	$url = isset ($_GET['url']) ? $_GET['url'] : "http://eloquentjavascript.net/";
	$contents = base64_encode(mb_convert_encoding(file_get_contents($url), "HTML-ENTITIES","UTF-8"));
	?>
<!doctype html>
<html>
	<head>
		<title>Fetch Page</title>
	<link rel="stylesheet" href="fetch_page.css">
	<script src="fetch_page.js"></script>
	<script>
	var BASE = "<?php echo $url; ?>";
	var PAGE = "<?php echo $contents; ?>";
	</script>
	</head>
	<body>
	<div id="searchBox">Type a URL here: <input type="text" id=urlBox"> <span id="goButton">GO</span></div>
	<div id="tocContainer">
	<div id="toc">[toc goes here]</div>
	<p id="contents">Hello World!</p>
	<div id="contents"></div>
	</body>
	</html>
3个回答

您的错误意味着什么?

Uncaught TypeError: Cannot read property 'addEventListener' of null. 
     at addEventListeners

归结为:

您尝试访问 addEventListeners 函数中某个对象的 addEventListener 属性,但该属性为 null

查看 addEventListeners

document.getElementById('goButton').addEventListener('click', submit);
document.getElementById('urlBox').addEventListener('keydown', function(event) {
    if (event.keyCode == 13 || event.keyCode == 10) {
        submit();
    }
});

其中一个 getElementsById 调用返回了 null,表示您的代码中没有这样的 ID。

查看 HTML 后,您会发现问题出在以下位置:

<input type="text" id=urlBox">

您缺少 ID 处的开头引号,因此实际上您已为元素指定了 urlBox" 的 ID(您 可以 省略用引号括住 HTML 属性,但不建议这样做)。

这就是 JS 找不到 ID 为 urlBox 的元素的原因>

FZs
2019-11-14

刚刚经历了类似的事情。将 defer 添加到我的脚本标记解决了该问题:

<script src="fetch_page.js" defer></script>

祝你好运!~E

Cherizer
2021-02-26

我也遇到过这个问题,我检查了我的代码,发现一切都正常。我意识到问题出在我放置脚本标记的位置,即 html 文件的头部,所以我将它放在 body 标记的末尾。我还从回答这个问题的一个人那里了解到,使用“defer”可以使它工作,无论脚本标记在哪里,只要它在 html 标记内即可。

Dickson Anthony
2021-11-17