简体   繁体   English

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

[英]Delete Specific <li> elements using JavaScript

The function does not seem to delete the Node containing the specified value unless it is first value (in this case 'apples'). 该函数似乎不会删除包含指定值的Node ,除非它是第一个值(在本例中为'apples')。 The for loop also has to execute twice before deletion of any kind. 在删除任何类型之前,for循环还必须执行两次。 Why is that so? 为什么会这样?

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");
   }
}

The corresponding HTML: 相应的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>

childNodes returns a list of all child nodes. childNodes返回所有子节点的列表。 That includes text nodes . 这包括文本节点 Between every <li> element you have a text node that contains spaces and a line break. 在每个<li>元素之间,您有一个包含空格和换行符的文本节点。 So, childNodes returns a list of 9 nodes, but you are assuming list of 4 nodes ( document.getElementsByClassName('fruit').length ). 因此, childNodes返回9个节点的列表,但是您假设有4个节点的列表( document.getElementsByClassName('fruit').length )。

You could use .children instead of .childNodes . 您可以使用.children而不是.childNodes .children returns a list of only element nodes . .children返回仅有元素节点的列表。 Or better yet, use elements , since that's what you are iterating over. 或者更好的是,使用elements ,因为这就是你正在迭代的东西。

You also need to stop iterating after you found an removed a node, otherwise you will be trying to access a position that doesn't exist anymore. 您还需要在找到已删除的节点后停止迭代,否则您将尝试访问不再存在的位置。

 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"); } } 
 <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> 


There are other things that could be improved (eg why not assign an actual boolean value to checker ?), but they are not related to your question. 还有其他事情可以改进(例如,为什么不为checker分配实际的布尔值?),但它们与您的问题无关。

Instead of for loop you can consider of doing it the below way. 而不是循环,你可以考虑采用以下方式。

check this snippet 检查这个片段

 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(); }); } 
 <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> 

Hope it helps 希望能帮助到你

This might sound crazy, but Chrome seems to parse your HTML unordered list into the following: 这可能听起来很疯狂,但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

Essentially, it appears to be creating a text node in your unordered list for each newline inside the tag. 从本质上讲,它似乎是在您的无序列表中为标记内的每个换行创建一个文本节点。 This also explains why deletion only occurs after you call the function a second time - it deletes the text node first, then it deletes the actual element on its second try. 这也解释了为什么只在第二次调用函数后才会发生删除 - 它首先删除文本节点,然后在第二次尝试时删除实际元素。

Simple converting your HTML to the following form solves the problem (but is not very pretty): 将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>

There are some workarounds that you can try using. 您可以尝试使用一些变通方法。 For example, you could try using the childNode.remove() method instead, though not all browsers support this. 例如,您可以尝试使用childNode.remove()方法,但并非所有浏览器都支持此方法。

Alternatively, something like this might also work: 或者,这样的事情也可能有效:

selectedChildNode.parentNode.removeChild(selectedChildNode);

I run this code. 我运行这段代码。 you should add this line 你应该添加这一行

elements[counter].remove();

instead of this line 而不是这一行

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

myList is an array of li element so removeChild on myList is logically not correct. myList是一个li元素数组,因此myList上的removeChild在逻辑上是不正确的。

Also, myList.childNodes doesn't make sense here. 此外, myList.childNodes在这里没有意义。

Try 尝试

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

here the problem is in myList.removeChild(myList.childNodes[ (counter) ]); 这里的问题出在myList.removeChild(myList.childNodes[ (counter) ]); because myList.childNodes node return 8 values instead of 4. We have elements array with 4 nodes, hence the removing from elements array yields a proper result 因为myList.childNodes节点返回8个值而不是4个。我们有元素数组有4个节点,因此从元素数组中删除会产生正确的结果

Try the code snippet below, 试试下面的代码段,

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");
       }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM