使用JavaScript删除特定的<li>元素

时间:2017-01-02 05:22:02

标签: javascript dom

该函数似乎不会删除包含指定值的Node,除非它是第一个值(在这种情况下&#39; apples&#39;)。在删除任何类型之前,for循环还必须执行两次。为什么会这样?

function removeSpec()
{
    var query = document.getElementById('spec').value;  /* Value inputted by user */
    elements = document.getElementsByClassName('fruit'); /* Get the li elements in the list */
    var myList = document.getElementById("myList3"); /* Var to reference the list */
    var length = (document.getElementsByClassName('fruit').length); /* # of li elements */
    var checker = 'false'; /* boolean-ish value to determine if value was found */

    for(var counter = 0; counter < length; counter ++)
    {
        if (elements[counter].textContent == query )
        {
             alert("Counter : " + counter);
             myList.removeChild(myList.childNodes[ (counter) ]);
             checker="true";
        }
    }
  if ( checker == "false") 
   {
       alert("Not Found");
   }
}

相应的HTML:

  <ul id="myList3">
                <li class="fruit" >Apples</li>
                <li class="fruit" >Oranges</li>
                <li class="fruit" >Banannas</li>
                <li class="fruit">Strawberry</li>
   </ul>
   <form> 
           Value: <input type="text" name="" value="" id="spec">
   <br><br>
    </form>
    <button type="button" style="height:20px;width:200px" href="javascript:void(0)" onclick="removeSpec()" > 

        Remove Specified 
   </button>

6 个答案:

答案 0 :(得分:13)

childNodes返回所有子节点的列表。这包括文本节点。在每个<li>元素之间,您有一个包含空格和换行符的文本节点。因此,childNodes返回9个节点的列表,但您假设有4个节点的列表(document.getElementsByClassName('fruit').length)。

您可以使用.children代替.childNodes.children仅返回元素节点的列表。或者更好的是,使用elements,因为那是你正在迭代的内容。

您还需要在找到已删除的节点后停止迭代,否则您将尝试访问不再存在的位置。

&#13;
&#13;
function removeSpec()
{
    var query = document.getElementById('spec').value;  /* Value inputted by user */
    elements = document.getElementsByClassName('fruit'); /* Get the li elements in the list */
    var myList = document.getElementById("myList3"); /* Var to reference the list */
    var length = (document.getElementsByClassName('fruit').length); /* # of li elements */
    var checker = 'false'; /* boolean-ish value to determine if value was found */

    for(var counter = 0; counter < length; counter ++)
    {
        if (elements[counter].textContent == query )
        {
             myList.removeChild(myList.children[ (counter) ]);
             // better: myList.removeChild(elements[counter]);
             checker="true";
             break;
        }
    }
  if ( checker == "false") 
   {
       alert("Not Found");
   }
}
&#13;
<ul id="myList3">
                <li class="fruit" >Apples</li>
                <li class="fruit" >Oranges</li>
                <li class="fruit" >Banannas</li>
                <li class="fruit">Strawberry</li>
   </ul>
   <form> 
           Value: <input type="text" name="" value="" id="spec">
   <br><br>
    </form>
    <button type="button" style="height:20px;width:200px" href="javascript:void(0)" onclick="removeSpec()" > 

        Remove Specified 
   </button>
&#13;
&#13;
&#13;

还有其他一些事情可以改进(例如,为什么不将实际的布尔值分配给checker?),但它们与您的问题无关。

答案 1 :(得分:1)

您可以考虑以下方式执行此操作,而不是for循环。

检查此代码段

&#13;
&#13;
function removeSpec() {
  var query = document.getElementById('spec').value; /* Value inputted by user */
  var elements = document.getElementsByClassName('fruit'); /* Get the li elements in the list */
  var myList = document.getElementById("myList3"); /* Var to reference the list */
  var length = (document.getElementsByClassName('fruit').length); /* # of li elements */
  var checker = 'false'; /* boolean-ish value to determine if value was found */

  myList.querySelectorAll('li').forEach(function(item) {
    if (item.innerHTML == query)
      item.remove();
  });
}
&#13;
<ul id="myList3">
  <li class="fruit">Apples</li>
  <li class="fruit">Oranges</li>
  <li class="fruit">Banannas</li>
  <li class="fruit">Strawberry</li>
</ul>
<form>
  Value:
  <input type="text" name="" value="" id="spec">
  <br>
  <br>
</form>
<button type="button" style="height:20px;width:200px" href="javascript:void(0)" onclick="removeSpec()">

  Remove Specified
</button>
&#13;
&#13;
&#13;

希望有所帮助

答案 2 :(得分:1)

这可能听起来很疯狂,但Chrome似乎会将您的HTML无序列表解析为以下内容:

NodeList[9]
0: text
1: li.fruit
2: text
3: li.fruit
4: text
5: li.fruit
6: text
7: li.fruit
8: text
length: 9
__proto__: NodeList

基本上,它似乎是在标签内的每个换行符的无序列表中创建一个文本节点。这也解释了为什么只在第二次调用函数后才会发生删除 - 它首先删除文本节点,然后在第二次尝试时删除实际元素。

将HTML简单地转换为以下形式可以解决问题(但不是很漂亮):

<ul id="myList3"><li class="fruit">Apples</li><li class="fruit">Oranges</li><li class="fruit">Banannas</li><li class="fruit">Strawberry</li></ul>

您可以尝试使用某些变通方法。例如,您可以尝试使用childNode.remove()方法,但并非所有浏览器都支持此功能。

或者,这样的事情也可能有效:

selectedChildNode.parentNode.removeChild(selectedChildNode);

答案 3 :(得分:0)

我运行此代码。你应该添加这一行

elements[counter].remove();

而不是这一行

myList.removeChild(myList.childNodes[ (counter) ]);

答案 4 :(得分:0)

myList是li元素的数组,因此removeChild myList上的myList.childNodes在逻辑上不正确。

此外,myList[counter].parentNode.removeChild(myList[counter]); 在这里没有意义。

尝试

testGrouping in Test := (definedTests in Test).value map { test =>
  Tests.Group(name = test.name, tests = Seq(test), runPolicy = Tests.SubProcess(
    ForkOptions(
      javaHome.value,
      outputStrategy.value,
      Nil,
      Some(baseDirectory.value),
      javaOptions.value,
      connectInput.value,
      envVars.value
    )))
}

答案 5 :(得分:0)

此问题出现在myList.removeChild(myList.childNodes[ (counter) ]);中,因为myList.childNodes节点返回8个值而不是4个。我们有元素数组有4个节点,因此从元素数组中删除会产生正确的结果

尝试下面的代码段,

function removeSpec() {
        var query = document.getElementById('spec').value;
        elements = document.getElementsByClassName('fruit');

        var myList = document.getElementById("myList3"); 
        var length = elements.length; 
        var checker = 'false'; 

        for(var counter = 0; counter < length; counter ++)
        {           
            if (elements[counter].textContent == query )
            {
                 alert("Counter : " + counter);
                 myList.removeChild(elements[counter]);
                 checker="true";
            }
        }
      if ( checker == "false") 
       {
           alert("Not Found");
       }
}