为什么JS函数在第一个HTML元素后停止执行?

huangapple go评论72阅读模式
英文:

Why does the JS function stop execution after the first html element?

问题

函数没有处理段落的原因是因为函数中的条件语句只处理节点类型为元素节点(Element Node)的情况,而段落 <p> 是元素节点,但代码中的条件语句没有考虑到它们。要处理段落,你可以修改 testFn 函数以包括对段落的处理。以下是修改后的代码:

function testFn(node) {
    node.childNodes.forEach(function(e) {
        testFn(e);

        if (e.nodeType !== Node.ELEMENT_NODE) {
            // 如果节点类型不是元素节点,替换为其子节点
            e.replaceWith(...e.childNodes);
        } else if (e.nodeName.toLowerCase() === 'p') {
            // 如果是 <p> 元素,将其文本内容替换为其子节点的文本内容
            e.textContent = e.textContent;
        }
    });
}

通过添加对 <p> 元素的条件处理,函数将处理段落,并将其文本内容替换为子节点的文本内容。这将产生你所需的输出。

英文:

It is necessary to leave only the li tags.
Of the other tags, leave only the text.

My code:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

let html = `
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;&lt;code&gt;foo&lt;/code&gt; link text&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;&lt;code&gt;bar&lt;/code&gt; link text&lt;/a&gt;;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Paragraph text &lt;code&gt;baz&lt;/code&gt; and &lt;code&gt;biz&lt;/code&gt; text.&lt;/p&gt;
&lt;p&gt;Paragraph text.&lt;/p&gt;
`;

html = `&lt;body&gt;${html}&lt;/body&gt;`;

let parsed = new DOMParser().parseFromString( html, &#39;text/html&#39; );

function testFn( node  ) {

    node.childNodes.forEach( function( e ) {

        testFn( e );

        if ( e.nodeType !== Node.ELEMENT_NODE ) return;

        if ( e.nodeName.toLowerCase() !== &#39;li&#39; ) {

            e.replaceWith( ...e.childNodes );
        }
    });
}

testFn( parsed.body );

console.log( parsed.body.innerHTML );

<!-- end snippet -->

Result:

&lt;li&gt;foo link text;&lt;/li&gt;
&lt;li&gt;bar link text;&lt;/li&gt;

&lt;p&gt;Paragraph text &lt;code&gt;baz&lt;/code&gt; and &lt;code&gt;biz&lt;/code&gt; text.&lt;/p&gt;
&lt;p&gt;Paragraph text.&lt;/p&gt;

And I need such a result:

&lt;li&gt;foo link text;&lt;/li&gt;
&lt;li&gt;bar link text;&lt;/li&gt;

Paragraph text baz and biz text.
Paragraph text.

Why doesn't the function handle paragraphs?

答案1

得分: 2

forEach() 不适合条件递归,仅会在传递的数组上增加复杂性并处理回调函数。以下是将您的逻辑转换为 for...of 循环的代码。

let html = `
<ol>
<li><a href="#"><code>foo</code> link text</a>;</li>
<li><a href="#"><code>bar</code> link text</a>;</li>
</ol>
<p>Paragraph text <code>baz</code> and <code>biz</code> text.</p>
<p>Paragraph text.</p>
`;

html = `<body>${html}</body>`;

let parsed = new DOMParser().parseFromString(html, 'text/html');

function testFn(node) {
  for (const childNode of node.childNodes) {
    testFn(childNode);

    if (childNode.nodeType !== Node.ELEMENT_NODE) {
      continue;
    }

    if (childNode.nodeName.toLowerCase() !== 'li') {
      childNode.replaceWith(...childNode.childNodes);
    }    
  }
}

testFn(parsed.body);

console.log(parsed.body.innerHTML);

希望这对您有帮助。

英文:

forEach() is not ideal for conditional recursion and only adds complexity in its closure over the passed array and handling of the callback. Here is your logic transposed to a for...of loop.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

let html = `
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;&lt;code&gt;foo&lt;/code&gt; link text&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;&lt;code&gt;bar&lt;/code&gt; link text&lt;/a&gt;;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Paragraph text &lt;code&gt;baz&lt;/code&gt; and &lt;code&gt;biz&lt;/code&gt; text.&lt;/p&gt;
&lt;p&gt;Paragraph text.&lt;/p&gt;
`;

html = `&lt;body&gt;${html}&lt;/body&gt;`;

let parsed = new DOMParser().parseFromString(html, &#39;text/html&#39;);

function testFn(node) {
  for (const childNode of node.childNodes) {
    testFn(childNode);

    if (childNode.nodeType !== Node.ELEMENT_NODE) {
      continue;
    }

    if (childNode.nodeName.toLowerCase() !== &#39;li&#39;) {
      childNode.replaceWith(...childNode.childNodes);
    }    
  }
}

testFn(parsed.body);

console.log(parsed.body.innerHTML);

<!-- end snippet -->

答案2

得分: 0

以下是代码部分的翻译:

你正在在迭代它们时更改`childNodes`使用副本就可以解决问题

let html = `
<ol>
<li><a href="#"><code>foo</code>链接文本</a>;</li>
<li><a href="#"><code>bar</code>链接文本</a>;</li>
</ol>
<p>段落文本<code>baz</code>和<code>biz</code>文本。</p>
<p>段落文本。</p>
`;

html = `<body>${html}</body>`;

let parsed = new DOMParser().parseFromString(html, 'text/html');

function testFn(node) {
  [...node.childNodes].forEach(function(e) {
    testFn(e);
  });
  
  [...node.childNodes].forEach(function(e) {
    if (e.nodeType !== Node.ELEMENT_NODE) return;

    if (e.nodeName.toLowerCase() !== 'li') {
      e.replaceWith(...e.childNodes);
    }

  });
}

testFn(parsed.body);
console.log(parsed.body.innerHTML);

请注意,我只翻译了代码部分,没有包括任何其他内容。

英文:

You are changing the childNodes while iterating over them. Use copies and it works:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

let html = `
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;&lt;code&gt;foo&lt;/code&gt; link text&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;&lt;code&gt;bar&lt;/code&gt; link text&lt;/a&gt;;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Paragraph text &lt;code&gt;baz&lt;/code&gt; and &lt;code&gt;biz&lt;/code&gt; text.&lt;/p&gt;
&lt;p&gt;Paragraph text.&lt;/p&gt;
`;

html = `&lt;body&gt;${html}&lt;/body&gt;`;

let parsed = new DOMParser().parseFromString(html, &#39;text/html&#39;);

function testFn(node) {
  [...node.childNodes].forEach(function(e) {
    testFn(e);
  });
  
  [...node.childNodes].forEach(function(e) {
    if (e.nodeType !== Node.ELEMENT_NODE) return;

    if (e.nodeName.toLowerCase() !== &#39;li&#39;) {
      e.replaceWith(...e.childNodes);
    }

  });
}

testFn(parsed.body);
console.log(parsed.body.innerHTML);

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年2月6日 20:34:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/75361376.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定