if语句中的javascript迭代

javascript iteration within if statement

本文关键字:javascript 迭代 语句 if      更新时间:2023-12-30

在这个JSFiddle中(问题代码注释掉),第一次点击空单元格将在隐藏输入中设置一个值,并将单元格的bgcolor设置为绿色。点击第二个空表格单元格,设置另一个隐藏输入的值,并将第二个单元格bgcolor更改为红色。

现在,根据另一个SO问题的反馈,我试图通过循环表中所有td的数组(所有注释掉的代码)来实现一个检查,看看onclick,任何单元格是否已经分别将bgcolor设置为绿色/红色,如果为true,则将bgcolor设置为空/空白,以允许NEW单元格选择获得bgcolor,所以应该总是只有一个绿色块和一个红色块。有人能向我解释一下我是如何实现循环并检查错误而没有得到预期结果的吗。

数组循环在这里起作用——当不是现有代码的一部分时,使用jsfiddle。但当我把它添加到需要的代码中时,它就不起作用了。

HTLM

<div id="starget"></div>
<div id="etarget"></div>
<table width="100%" id="test">
    <thead>
        <tr>
            <th>Tech</th>
            <th>0800</th>
            <th>0900</th>
            <th>1000</th>
            <th>1100</th>
            <th>1200</th>
        </tr>
    </thead>
    <tr>
        <td>Bill</td>
        <td>XXX</td>
        <td onclick="res(0900,this);"></td>
        <td>XXX</td>
        <td>XXX</td>
        <td onclick="res(1200,this);"></td>
    </tr>
</table>

脚本

var x = 0;
var click = 0;
/* tdElements = document.getElementsByTagName("td"); */
/* I have tried the tdelements array inside and outside of the function */
function res(zz,el) {
    if (click == 0) {
        /* for(var key in tdElements) { 
            if (tdElements[key].style.backgroundColor=="green") {
                tdElements[key].style.backgroundColor="";
            }
        } */
        document.getElementById('starget').innerHTML=zz;
        click = 1;
        el.style.backgroundColor='green';
    }
    else {
        /* for(var key in tdElements) { 
            if (tdElements[key].style.backgroundColor=="red") {
                tdElements[key].style.backgroundColor="";
            }
        } */
        document.getElementById('etarget').innerHTML=zz;
        click = 0;
        el.style.backgroundColor='red';
    }
}

如果调用.getElementsByTagName,则不会返回array!您将返回一个liveHTMLCollection元素,其中包含一些在使用for.. in循环时无法忽略的其他项目。for循环将派上用场,因为您的实时HTMLCollection包含您可以使用的length

/* HTMLCollections come with a length attribute we can use 
 * as every item is numbered, but in a object-style key-value pair */
for(var i = 0; i < tdElements.length; i++){
    /* This was tripping up your code - the `item` function to fetch an
     * element at the index defined in the HTMLCollection*/
    tdElements.item(i).style.backgroundColor = "green"
}

这将使所有背景变为绿色。现在你将不得不修改你的代码,但这就是它的工作方式。更多信息请点击此处:https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection

您真正想要做的是使用class而不是style来处理此问题。原因是使用getElementsByClassName可以非常容易地提取具有特定类的所有元素(注意:在IE 9及更高版本中)。

在不过分偏离您的方法的情况下(我确实提高了它的效率:),您的代码需要更改为:

CSS:

.firstClick {background-color: green;}
.secondClick {background-color: red;}

脚本:

var click = 0;
function res(zz,el) {
    var currentlyClickedEls, currClass, divTarget;
    if (click === 0) {
        currClass = "firstClick";
        divTarget = "starget";
        click = 1;
    }
    else {
        currClass = "secondClick";
        divTarget = "etarget";
        click = 0;
    }
    // get all the elements with the appropriate class
    currentlyClickedEls = document.getElementsByClassName(currClass);
    // remove that class from those elements
    while (currentlyClickedEls.length > 0) {
        currentlyClickedEls[0].className = "";
    }
    // add the class to the clicked element
    el.className = currClass;
    document.getElementById(divTarget).innerHTML = zz;
}

使用这种方法,单击时,您要做的第一件事就是找到类firstClicksecondClick的所有元素(基于click的值),并移除该类。由于最多只能有一个,这使得要经过一个非常短的循环(但如果以某种方式发生,也会从多个元素中删除类)。

编辑:

因此,您不会在代码中注意到这一点,因为这两个类中的每一个都没有超过一个实例,但是,正如前面所指出的,我们正在处理DOM元素的LIVE集合,因此,当您从元素中删除类时(从中删除类的元素),就会从集合中掉出来。

例如,在表的第三次单击时,集合中会有一个元素由document.getElementsByClassName(currClass);=HTMLCollection[td.firstClick](在控制台中)返回。但是,一旦从元素中删除了该类,它就不再符合条件,因此集合变为空(即HTMLCollection[])。

因此,尽管它适用于您的情况(因为它在i = 1上停止,因为它仍然"不小于"集合的新长度(现在是0)。

然而,在其他情况下,情况可能并非如此。例如,如果返回了2个元素,在第一个元素的类被删除后,i将变为1,但长度也将降至1,循环将停止,而不处理第二个元素。

因此,确实需要改变方法来正确处理这种行为。我通过更改这些行做到了这一点:

    for (i = 0; i < currentlyClickedEls.length; i++) {
        currentlyClickedEls[i].className = "";

到这些线路:

    while (currentlyClickedEls.length > 0) {
        currentlyClickedEls[0].className = "";

这样,删除其类的元素始终是集合中的第一个元素,while循环在尝试删除该类之前进行检查以确保集合中仍有元素。

因此,长话短说,当处理HTML集合时,正如somethinghere所指出的,您正在处理DOM元素的实时集合,因此,如果您做出的更改会影响该集合中包含的单个元素,它将相应地更新集合,并且您需要能够在代码中对此进行说明。