【问题标题】:document.getElementById returns null value [duplicate]document.getElementById 返回空值
【发布时间】:2017-03-26 07:46:25
【问题描述】:

您好,我有这些 div:

<div 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 id="layoutGroup2">
    <div id="tree"></div>
</div>
<div id="layoutGroup3">
    <div id="map"></div>
</div>

我希望在屏幕上显示三个按钮,然后单击以隐藏两个 div 并只显示一个。

button id="userButton" onclick ="showOnClick('layoutGroup1');">ECA </button
function showOnClick(element) {
    if (element == 'layoutGroup1') {
        document.getElementById('layoutGroup1').style.display == 'block';
        document.getElementById('layoutGroup2').style.display == 'none';
        document.getElementById('layoutGroup3').style.display == 'none';
    } else if (element == 'layoutGroup2') {
        document.getElementById("layoutGroup1").style.display == 'none';
        document.getElementById("layoutGroup2").style.display == 'block';
        document.getElementById('layoutGroup3').style.display == 'none';
    } else {
        document.getElementById("layoutGroup3").style.display == "block";
        document.getElementById("layoutGroup1").style.display == "none";
        document.getElementById("layoutGroup2").style.display == "none";
    }
 }

上面是我使用的函数,虽然它给了我一个错误,getElementByIDnull

【问题讨论】:

  • 包装此代码或在 window.onload 中调用 showOnClick ...它应该可以工作
  • 为什么在 if 语句体中使用 equal 语句 == 而不是 =?我想你想设置 style.display 不比较。您是否在尝试在 JS 中访问的 HTML 元素之后加载 JS 脚本?
  • 是的,你是对的。感谢您的关注?
  • 您找到解决方案了吗?我遇到了同样的问题,看不到任何这些答案来解决它:/

标签: javascript html


【解决方案1】:

getElementById() 获取null 以获取HTML 中的元素

您从对getElementById() 的调用中获取null 的具体问题可能是由于您的JavaScript 在页面的HTML 完全加载之前运行引起的(即元素在DOM 中尚不存在,因此@ 987654329@)。但是,虽然这可能是问题所在,但我们无法知道这是问题所在,因为您的问题并未向我们展示您的 HTML 和 JavaScript 之间的关系(即不显示 JavaScript 在页面中加载/运行的方式和时间)。

在页面中的元素可用之前运行 JavaScript 问题的解决方案是将 JavaScript 的执行延迟到 page has loaded。有多种方法可以做到这一点。一种是在 HTML 底部添加 &lt;script&gt; 标签。但是,延迟到页面加载通常是通过将您的代码(或只是您的初始化代码)包装在一个函数中来完成的,然后将其分配为在@987654331 的各个阶段触发的各种事件之一的侦听器@准备好了。最常用的是&lt;document&gt;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。

【讨论】:

  • 非常感谢您提供有用的答案。
【解决方案2】:

虽然您没有为这个问题指定 jQuery - 有一个非常简单的 jquery 方法。有三个按钮,每个按钮都有一个对应于 div 的值。然后在 onclick 事件中(并注意通过删除内联单击处理程序将 javascript 与 html 分离 - 更好的代码结构) - 您只需获取单击按钮的值,隐藏()所有 div(使用公共类)然后使用其 id 显示()所需的一个。这也可以通过添加/删除一个隐藏类来完成(例如 .hidden{display:none},它可以使用 vanilla javascript 来完成 - 但所有这些如果......请注意,我在 div2 和 3 中添加了一些文本这样就可以看到它们在各自的按钮点击中切换。

请注意,我并不是建议为这个函数加载整个 jQuery 库——这个小函数的权重太大,而只是提供一个允许小函数成为代码结构的一部分的选项。

$(document).ready(function(){
  $('.showDiv').click(function(){
    var element = $(this).val();
    $('.layoutGroups').hide();
    $('#layoutGroup'+element).show(); 
  })
})
<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>

【讨论】:

  • 虽然 jQuery 有许多方便的功能,但您可以编写功能上与现有 JavaScript 相同的代码,只需使用更多字符。一个快速的、非优化的、逐行等效的 JavaScript 实现需要大约 338 个字符,而这个 jQuery 解决方案需要 149 个字符(jQuery 节省了 189 个字符)。适度的大小优化可以将 JavaScript 版本减少到 307 个字符,比等效的 jQuery 多 111 个(ES6 节省了另外 50 个左右的 JavaScript)。没有可用的 jQuery 并不意味着你不应该类似地考虑这个问题。
  • 是的,谢谢你的建议,我正在使用 javascript,不幸的是没有提到它
【解决方案3】:

function showOnClick(element){

    if(element=='layoutGroup1'){
        document.getElementById('layoutGroup1').style.display='block';
        document.getElementById('layoutGroup2').style.display='none';
        document.getElementById('layoutGroup3').style.display='none';
    }
    else if(element=='layoutGroup2'){
        document.getElementById("layoutGroup1").style.display='none';
        document.getElementById("layoutGroup2").style.display='block';
        document.getElementById('layoutGroup3').style.display='none';
    }
    else{
        document.getElementById("layoutGroup3").style.display="block";
        document.getElementById("layoutGroup1").style.display="none";
        document.getElementById("layoutGroup2").style.display="none";
    }
}
#layoutGroup1, #layoutGroup2, #layoutGroup3{
    display: none;  
}
    <button id="userButton1" onclick ="showOnClick('layoutGroup1');">ECA </button>

<button id="userButton2" onclick ="showOnClick('layoutGroup2');">button 2 </button>

<button id="userButton3" onclick ="showOnClick('layoutGroup3');">button 3 </button>

<div id="layoutGroup1">
    <h2>UK Map</h2>
    <div div style="width: 650px; height: 700px;" id="MapDIV"></div>
    <div id="userUpdateDIV">this is layoutGroup1</div>
    <div id="BarChartDIV"></div>
    <div id="divPack1"></div>
</div>
<div id="layoutGroup2">
    <div id="tree">this is layoutGroup2</div>
</div>
<div id="layoutGroup3">
    <div id="map">this is layoutGroup3</div>
</div>

这是你的修正函数

function showOnClick(element){

    if(element=='layoutGroup1'){
        document.getElementById('layoutGroup1').style.display='block';
        document.getElementById('layoutGroup2').style.display='none';
        document.getElementById('layoutGroup3').style.display='none';
    }
    else if(element=='layoutGroup2'){
        document.getElementById("layoutGroup1").style.display='none';
        document.getElementById("layoutGroup2").style.display='block';
        document.getElementById('layoutGroup3').style.display='none';
    }
    else{
        document.getElementById("layoutGroup3").style.display="block";
        document.getElementById("layoutGroup1").style.display="none";
        document.getElementById("layoutGroup2").style.display="none";
    }
}

if 条件下,== 表示将 LHs 与 RHS 进行比较,=display='block' 中用作赋值运算符,将右侧的值分配给左侧的对象

【讨论】:

  • 是的,谢谢你,我的函数的问题是不小心使用 double == 将显示值分配给 div
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-13
  • 2023-03-25
  • 1970-01-01
  • 2015-02-02
  • 2011-11-01
  • 1970-01-01
相关资源
最近更新 更多