Javascript 从html集合中删除outerHTML中的元素

Javascript 从html集合中删除outerHTML中的元素,javascript,dom,htmlcollection,Javascript,Dom,Htmlcollection,我有以下代码。我试图通过将outerHTML设置为空(“”)来删除元素。我还对html集合进行了一些研究,发现它是一个实时的集合 裁判: 所以我所知道的是,如果我更改了文档,那么列表应该会更改。代码证明了这种行为,循环运行了4次,尽管我的初始html集合长度为9。现在,当我用innerHTML替换outerHTML时,循环进行了9次。因此,如果列表应该随着文档的更改而更新,为什么在我用innerHTML替换outerHTML时不会发生这种情况呢 function expTble()

我有以下代码。我试图通过将outerHTML设置为空(“”)来删除元素。我还对html集合进行了一些研究,发现它是一个实时的集合

裁判:
所以我所知道的是,如果我更改了文档,那么列表应该会更改。代码证明了这种行为,循环运行了4次,尽管我的初始html集合长度为9。现在,当我用innerHTML替换outerHTML时,循环进行了9次。因此,如果列表应该随着文档的更改而更新,为什么在我用innerHTML替换outerHTML时不会发生这种情况呢

function expTble() {


    let tables = document.getElementsByTagName("table")

    let captions = document.getElementsByTagName("caption")


    if (captions.length > 1) {
        
        console.log(`${tables.length} tables ${captions.length} captions`)

        for (let i = 0; i < captions.length; i++) {

            console.log('index : ' + i)
         
            captions[i].outerHTML = ''

        }

        return

    }

    for (let i = 0; i < tables.length; i++) {
        // Do stuffs
        TableExport(tables[i], { bootstrap: false })
    }



}
使用innerHTML时
当live集合所引用的元素发生更改时,live集合会自动更新。在您的情况下,outerHTML会更改元素,从而更新集合。但是innerHTML是一个不同的部分。它不是集合引用的内容,因此对子元素的更改不会更新html集合

如果要使用相同的逻辑删除元素,请使用While循环并检查长度是否为0,然后按第0个索引引用删除元素

 if (captions.length > 1) {

        while (captions.length > 0) {
            captions[0].outerHTML = ''
        }

        return

    }

当live集合所引用的元素发生更改时,live集合会自动更新。在您的情况下,outerHTML会更改元素,从而更新集合。但是innerHTML是一个不同的部分。它不是集合引用的内容,因此对子元素的更改不会更新html集合

如果要使用相同的逻辑删除元素,请使用While循环并检查长度是否为0,然后按第0个索引引用删除元素

 if (captions.length > 1) {

        while (captions.length > 0) {
            captions[0].outerHTML = ''
        }

        return

    }

这是因为您在一个引用数组上向前(0->n)迭代,同时操作它的长度。 当您删除元素
i
时,您正在积极地缩短数组。 如本例所示:

let arr = ['A','B','C','D','E','F'];
console.log('started');
for (let i = 0; i < arr.length; i++) {
    var removed = arr.splice(i, 0);
    console.log('i:'+i,'Arr:',arr, '(removed ' + i + ')');
}
console.log('ended');
但是,如果您选择在何处修改for循环以进行反向迭代,则不会出现此问题,因为您总是以未删除的元素为目标

for (let i = captions.length - 1; i >= 0; i--) {
        ...
    }

6 tables 6 captions
index : 5
index : 4
index : 3
index : 2
index : 1
index : 0
那么,为什么只有在使用outerHtml时才会发生这种情况呢?
原因是
x.innerHtml=“”
清除元素的内容(
test
->
),而
x.outerHtml=“”
覆盖元素本身(
test
->
)。

这是由于您正在向前迭代(0->n)这一事实造成的在一个引用数组上,同时操纵它的长度。 当您删除元素
i
时,您正在积极地缩短数组。 如本例所示:

let arr = ['A','B','C','D','E','F'];
console.log('started');
for (let i = 0; i < arr.length; i++) {
    var removed = arr.splice(i, 0);
    console.log('i:'+i,'Arr:',arr, '(removed ' + i + ')');
}
console.log('ended');
但是,如果您选择在何处修改for循环以进行反向迭代,则不会出现此问题,因为您总是以未删除的元素为目标

for (let i = captions.length - 1; i >= 0; i--) {
        ...
    }

6 tables 6 captions
index : 5
index : 4
index : 3
index : 2
index : 1
index : 0
那么,为什么只有在使用outerHtml时才会发生这种情况呢?
原因是
x.innerHtml=“”
清除元素的内容(
test
->
),而
x.outerHtml=“”
覆盖元素本身(
test
->
)。

您自己回答了这个问题:“这是一个实时收藏”。在迭代过程中删除活动集合中的元素会缩短集合,此时您将跳过下一个成员。将innerHTML设置为空字符串不会影响元素的外部HTML,因此它会保留在集合中(以及DOM中)。删除元素时,将
i
减少1,使用
querySelectorAll
获取静态集合,或向后迭代实时集合以解决问题。@Teemu因此只有outerHTML(属性和内容)上的更改才会反映在集合中?是,该集合只是由创建该集合的方法指定的元素的引用集合(或者在
querySelectorAll
的情况下由选择器指定)。其中任何一个都不是指收集的元素中的元素。您自己已经回答了这个问题:“这是一个实时收集”。在迭代过程中删除活动集合中的元素会缩短集合,此时您将跳过下一个成员。将innerHTML设置为空字符串不会影响元素的外部HTML,因此它会保留在集合中(以及DOM中)。删除元素时,将
i
减少1,使用
querySelectorAll
获取静态集合,或向后迭代实时集合以解决问题。@Teemu因此只有outerHTML(属性和内容)上的更改才会反映在集合中?是,该集合只是由创建该集合的方法指定的元素的引用集合(或者在
querySelectorAll
的情况下由选择器指定)。其中任何一个都没有引用收集的元素内部的元素。您已经指出了一个非常好的逻辑,使用for循环的顺序是相反的谢谢您已经指出了一个非常好的逻辑,使用for循环的顺序是相反的谢谢