从getElementById() 获取null 以获取HTML 中的元素
您从对getElementById() 的调用中获取null 的具体问题可能是由于您的JavaScript 在页面的HTML 完全加载之前运行引起的(即元素在DOM 中尚不存在,因此@ 987654329@)。但是,虽然这可能是问题所在,但我们无法知道这是问题所在,因为您的问题并未向我们展示您的 HTML 和 JavaScript 之间的关系(即不显示 JavaScript 在页面中加载/运行的方式和时间)。
在页面中的元素可用之前运行 JavaScript 问题的解决方案是将 JavaScript 的执行延迟到 page has loaded。有多种方法可以做到这一点。一种是在 HTML 底部添加 <script> 标签。但是,延迟到页面加载通常是通过将您的代码(或只是您的初始化代码)包装在一个函数中来完成的,然后将其分配为在@987654331 的各个阶段触发的各种事件之一的侦听器@准备好了。最常用的是<document> 的DOMContentLoaded event。您可以使用以下代码执行此操作:
//Wait to run your initialization code until the DOM is fully loaded. This is needed
// when wanting to access elements that are later in the HTML than the <script>.
if(document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', afterLoaded);
} else {
//The DOMContentLoaded event has already fired. Just run the code.
afterLoaded();
}
afterLoaded() {
//Your initialization code goes here. This is from where your code should start
// running if it wants to access elements placed in the DOM by your HTML files.
// If you are wanting to access DOM elements inserted by JavaScript, you may need
// to delay more, or use a MutationObserver to see when they are inserted.
});
该事件也可以通过document.onready 访问。当多个脚本尝试这样做时,以这种方式访问它可能会导致问题,因为只有一个人可以使用这种方法。因此,最好使用addEventListener() 方法来侦听此事件或任何其他事件。
代码的其他方面
在his answer 中,gavgrif 对代码结构提出了一些好处,包括通过使用 JavaScript 添加事件侦听器来将 HTML 与 JavaScript 分开,并通过首先将 all 设置为 not 来消除 if 语句的字符串可见,然后设置您想要可见的那个。在他的回答中,暗示您必须使用 jQuery 来考虑使用不同结构的问题。 jQuery 提供了许多方便的功能。它最重要的功能之一是跨浏览器兼容性。但是,它还提供了大量预定义的方法,这些方法允许对常用功能进行简短的语法访问,在大多数情况下,这些方法会隐式迭代所有选择的元素。这一切都以 85KiB 的最小化代码为代价。因此,如果您只做一些事情,那么 jQuery 是不合适的。
您可以使用 vanilla JavaScript 实现 gavgrif 在他的回答中显示的相同功能。
document.addEventListener('DOMContentLoaded', function(){
//Wait to add event listeners until the DOM is fully loaded. This is needed
// when wanting to access elements that are later in the HTML than the <script>.
queryAll('.showDiv').forEach(function(el){
el.addEventListener('click',showOnClick);
});
});
function showOnClick(event){
var groupNumber=this.value;
queryAll('.layoutGroups').forEach(function(el){
el.style.display='none'
});
document.querySelector('#layoutGroup'+groupNumber).style.display='block';
}
function queryAll(selector){
return asArray(document.querySelectorAll(selector))
}
function asArray(obj){
var newArr = [];
newArr.push.apply(newArr, obj);
return newArr;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class='showDiv' value="1">1</button>
<button class='showDiv' value="2">2</button>
<button class='showDiv' value="3">3</button>
<div class="layoutGroups" id="layoutGroup1">
<h2>UK Map</h2>
<div div style="width: 650px; height: 700px;"id = "MapDIV"></div>
<div id="userUpdateDIV"></div>
<div id = "BarChartDIV"></div>
<div id="divPack1"></div>
</div>
<div class="layoutGroups" id="layoutGroup2">
<div id= "tree">Tree</div>
</div>
<div class="layoutGroups" id="layoutGroup3">
<div id = "map">Map</div>
</div>
更通用/可重用的代码:
一般来说,我更喜欢通用的show() 和hide() 函数,因为它们可能会在其他地方重复使用。此外,通过处理多种类型的输入(这里大部分不需要),以下内容使asArray() 更加健壮。
document.addEventListener('DOMContentLoaded', function(){
//Wait to add event listeners until the DOM is fully loaded. This is needed
// when wanting to access elements that are later in the HTML than the <script>.
queryAll('.showDiv').forEach(function(el) {
el.addEventListener('click',showOnClick)
});
});
function showOnClick(event){
var groupNumber = this.value;
hide(queryAll('.layoutGroups'));
show(queryDoc('#layoutGroup'+groupNumber));
}
function hide(arraylikeOrElement) {
setDisplay(arraylikeOrElement,'none')
}
function show(arraylikeOrElement) {
setDisplay(arraylikeOrElement,'block')
}
function setDisplay(arraylikeOrElement,text) {
setAStyle(arraylikeOrElement,'display',text);
}
function setAStyle(arraylikeOrElement,which,text) {
asArray(arraylikeOrElement).forEach(function(el) {
el.style[which]=text;
});
}
function queryAll(selector){
//Returns all matches in the document
return asArray(document.querySelectorAll(selector));
}
function queryDoc(selector){
//Returns only the first match in the document (useful for IDs). This is faster
// than querySelectorAll because it does not search the entire DOM. It stops
// after the first match.
return document.querySelector(selector);
}
function asArray(obj) {
//accepts Arrays, array-like Objects (e.g. NodeLists), single elements, primitives
// returns an array, even if the array only has one entry
var newArr = [];
if(typeof obj !== 'object' || obj instanceof Node) {
return [obj];
}
if(Array.isArray(obj)){
return obj;
}
if(obj === null) {
return null;
}
if(typeof obj.length === 'number') {
//NodeList and other array-like objects: faster in most browsers and
// more compatible than Array.from().
newArr.push.apply(newArr, obj);
return newArr;
}
if(typeof obj.nextNode === 'function') {
//e.g. TreeWalkers, NodeIterator
var currentNode;
while(currentNode = nodeIter.nextNode()) {
newArr.push(currentNode);
}
return newArr;
}
if(typeof Array.from === 'function') {
return Array.from(obj);
}
//Could make this much more complex to handle more types of Objects, but not in
// this demo code.
//Indicate that we don't know what to do with the Object
return null;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class='showDiv' value="1">1</button>
<button class='showDiv' value="2">2</button>
<button class='showDiv' value="3">3</button>
<div class="layoutGroups" id="layoutGroup1">
<h2>UK Map</h2>
<div div style="width: 650px; height: 700px;"id = "MapDIV"></div>
<div id="userUpdateDIV"></div>
<div id = "BarChartDIV"></div>
<div id="divPack1"></div>
</div>
<div class="layoutGroups" id="layoutGroup2">
<div id= "tree">Tree</div>
</div>
<div class="layoutGroups" id="layoutGroup3">
<div id = "map">Map</div>
</div>
更简洁的代码:
如果您希望代码简洁,可以执行以下操作 [注意:使用 ES6 语法可以进一步减少使用的字符数。]:
var d=document,q=function(s){return Array.prototype.slice.call(d.querySelectorAll(s))};
d.onready=function(){ //Using document.ready is not a good idea, use addEventListener.
q('.showDiv').forEach(function(e){e.addEventListener('click',function(){
var element=this.value;
q('.layoutGroups').forEach(function(e){e.style.display='none'});
q('#layoutGroup'+element)[0].style.display='block';
})})
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class='showDiv' value="1">1</button>
<button class='showDiv' value="2">2</button>
<button class='showDiv' value="3">3</button>
<div class="layoutGroups" id="layoutGroup1">
<h2>UK Map</h2>
<div div style="width: 650px; height: 700px;"id = "MapDIV"></div>
<div id="userUpdateDIV"></div>
<div id = "BarChartDIV"></div>
<div id="divPack1"></div>
</div>
<div class="layoutGroups" id="layoutGroup2">
<div id= "tree">Tree</div>
</div>
<div class="layoutGroups" id="layoutGroup3">
<div id = "map">Map</div>
</div>
以上代码sn-ps使用gavgrif's answer中提供的HTML。