从CodePen导出的JavaScript代码单页运行失败求助
问题分析与解决方案
你遇到的问题核心是DOM加载顺序导致的。你的JavaScript代码放在了<head>标签里,浏览器是从上到下解析HTML的,当脚本执行时,<body>里的<input>和<ul>元素还没有被创建出来,所以document.getElementById("users-list")和document.getElementById('filter_users')都会返回null,后续的渲染和事件绑定自然就无法正常工作。
下面给你三种可行的修复方案,任选其一都能解决问题:
方案1:把脚本移到末尾
这是最简单直接的方法,让脚本在所有DOM元素都加载完成后再执行:
<html> <head> <style> #filter_users { width:100%; padding:10px; } #users-list { margin:0; padding:0; } #users-list li { list-style:none; padding:10px; margin:5px 0; border: 1px solid #e4e4e4; } </style> </head> <body> <input type="text" placeholder="Search Users" id="filter_users"/> <ul id="users-list"> </ul> <script> var users = [ 'Goku', 'Naruto', 'Ichigo', 'Flash', 'Batman', 'Sherlock Holmes', 'Khaleesi', 'Steve Fox' ]; const ul = document.getElementById("users-list"); var render_lists = function(lists) { var li = ""; for (index in lists) { li += "<li>" + lists[index] + "</li>"; } ul.innerHTML = li; } render_lists(users); // lets filters it const input = document.getElementById('filter_users'); var filterUsers = function(event) { const keyword = input.value.toLowerCase(); const filtered_users = users.filter(function(user) { user = user.toLowerCase(); return user.indexOf(keyword) > -1; }); render_lists(filtered_users); } input.addEventListener('keyup', filterUsers); </script> </body> </html>
方案2:使用DOMContentLoaded事件监听
如果想保持脚本在<head>里,可以监听DOMContentLoaded事件,等DOM完全加载后再执行代码:
<html> <head> <style> #filter_users { width:100%; padding:10px; } #users-list { margin:0; padding:0; } #users-list li { list-style:none; padding:10px; margin:5px 0; border: 1px solid #e4e4e4; } </style> <script> document.addEventListener('DOMContentLoaded', function() { var users = [ 'Goku', 'Naruto', 'Ichigo', 'Flash', 'Batman', 'Sherlock Holmes', 'Khaleesi', 'Steve Fox' ]; const ul = document.getElementById("users-list"); var render_lists = function(lists) { var li = ""; for (index in lists) { li += "<li>" + lists[index] + "</li>"; } ul.innerHTML = li; } render_lists(users); // lets filters it const input = document.getElementById('filter_users'); var filterUsers = function(event) { const keyword = input.value.toLowerCase(); const filtered_users = users.filter(function(user) { user = user.toLowerCase(); return user.indexOf(keyword) > -1; }); render_lists(filtered_users); } input.addEventListener('keyup', filterUsers); }); </script> </head> <body> <input type="text" placeholder="Search Users" id="filter_users"/> <ul id="users-list"> </ul> </body> </html>
方案3:给脚本标签添加defer属性
defer属性会告诉浏览器推迟脚本的执行,直到DOM加载完成,同时脚本会保持原本的顺序:
<html> <head> <style> #filter_users { width:100%; padding:10px; } #users-list { margin:0; padding:0; } #users-list li { list-style:none; padding:10px; margin:5px 0; border: 1px solid #e4e4e4; } </style> <script defer> var users = [ 'Goku', 'Naruto', 'Ichigo', 'Flash', 'Batman', 'Sherlock Holmes', 'Khaleesi', 'Steve Fox' ]; const ul = document.getElementById("users-list"); var render_lists = function(lists) { var li = ""; for (index in lists) { li += "<li>" + lists[index] + "</li>"; } ul.innerHTML = li; } render_lists(users); // lets filters it const input = document.getElementById('filter_users'); var filterUsers = function(event) { const keyword = input.value.toLowerCase(); const filtered_users = users.filter(function(user) { user = user.toLowerCase(); return user.indexOf(keyword) > -1; }); render_lists(filtered_users); } input.addEventListener('keyup', filterUsers); </script> </head> <body> <input type="text" placeholder="Search Users" id="filter_users"/> <ul id="users-list"> </ul> </body> </html>
另外提个小建议:我给代码里的变量加上了const声明,尽量避免使用无声明的全局变量,长期来看能减少变量污染引发的潜在问题。
内容的提问来源于stack exchange,提问作者user ct
相关产品推荐
相关产品推荐

