Javascript 句子中的有色元素在跨度内时会失去颜色

Javascript 句子中的有色元素在跨度内时会失去颜色,javascript,Javascript,首先,我改变一个句子中两个单词的颜色。然后我把句子中的所有单词都用一个空格括起来,但是这两个单词的颜色消失了。你能不能请人解释一下我做错了什么 //首先我改变句子中两个单词的颜色 k1=document.getElementById('Example').innerText; k1=k1.replace('my-own','my-own')) document.getElementById('Example').innerHTML=k1; //然后我把这个句子的所有单词都用一个空格括起来 //

首先,我改变一个句子中两个单词的颜色。然后我把句子中的所有单词都用一个空格括起来,但是这两个单词的颜色消失了。你能不能请人解释一下我做错了什么

//首先我改变句子中两个单词的颜色
k1=document.getElementById('Example').innerText;
k1=k1.replace('my-own','my-own'))
document.getElementById('Example').innerHTML=k1;
//然后我把这个句子的所有单词都用一个空格括起来
//但这两个词的颜色消失了
k2=document.getElementById('Example').innerText.split(/\s/);
//将每个单词用一个空格括起来
var-word='';
var内容=“”;
for(k2的单词){
content+=`${word}`;
}
document.getElementById('newExample')。innerHTML=content
.color{
颜色:黄色;
}
这是我自己的例子

使用innerHTML保留标记,但不要仅通过
/\s/
进行拆分,而是向正则表达式中添加更多信息,以便它忽略HTML标记中的空格。我们可以使用负查找来完成此操作,搜索空格前面的
字符。这看起来像:

/(?<!<([^>]*))\s/g
let k1 = document.getElementById('Example').innerText;
k1 = k1.replace('my own', `<span class="color">my own</span>`)
document.getElementById('Example').innerHTML = k1;

let nodeList = document.getElementById('Example').childNodes;
let content = '';
for (let i = 0; i < nodeList.length; i++) {
  if (nodeList[i].nodeType === Node.TEXT_NODE) {
    const splitText = nodeList[i].nodeValue.split(/\s/);
    splitText.forEach(piece => {
      content += `<span>${piece}</span> `;
    })
  } else {
    content += `<span>${nodeList[i].outerHTML}</span> `;
  }
}

document.getElementById('newExample').innerHTML = content;
编辑:经过测试,我发现这个特殊的正则表达式在空格处分裂时返回一个
未定义的
元素。这不会影响其他元素,只是意味着在将其添加到内容之前,我们需要检查是否定义了
word
。请参见上面修改的代码

简短回答: 如果希望在保留所有标记的同时获取节点的内容,则需要查找

然而,从您试图实现的目标来看,您可能会从使用中受益更多

这是沙箱里的沙子


问题: innerText属性将仅保留节点内部的文本:

HTMLElement.innerText:表示元素呈现的文本内容的DOMString。()

这意味着它将除去元素中的所有标记(及其属性,包括类名)

因此,您不是将这些新元素包装到span标记中,而是将它们的内容复制到新创建的没有类名的span标记中。并有效地取消了以前设置的类名


解决方案1: 使用outerHTML获取节点HTML的字符串表示形式。这将保留所有标记,包括它们的属性(以及类)。这样做的副作用是,您不能再在每个空格字符处拆分此字符串,以仅获取有意义的单词;您还可以获得标签的所有字符

可以通过如下正则表达式分隔单词和由标记括起的单词:

(<\s*\w+?[^>]*>.*?<\s*\/\s*\w+>|\w+|[!?@#$%*.&]*)
(]*>.*?\w+[!?@$%*。&]*)

正则表达式可能会变得棘手。它们让你可以控制如何分离、捕获和操纵角色,但一开始它们看起来毫无意义

不过,你可能不需要它。如果您只想将一个句子中的每个单词都包装成一个跨度(无论是否使用标记),我建议您使用childNodes:


解决方案2: childNodes是一个只读属性,返回给定元素的所有子节点的节点列表。元素内部的文本也被视为节点(一个文本节点),标记是元素节点。有很多,但这两个是与您的示例最相关的

这里的战略是:

  • 使用childNodes获取元素内容的列表,包括文本和标记
  • 将纯文本节点与其他标记内部的文本分开
  • 文本节点不会自动拆分为单词,因此我们仍然需要拆分它们
  • 将每个拆分的单词包装在span元素中
  • 将每个标记包装在一个跨度元素中
  • 这是代码的样子:

    /(?<!<([^>]*))\s/g
    
    let k1 = document.getElementById('Example').innerText;
    k1 = k1.replace('my own', `<span class="color">my own</span>`)
    document.getElementById('Example').innerHTML = k1;
    
    let nodeList = document.getElementById('Example').childNodes;
    let content = '';
    for (let i = 0; i < nodeList.length; i++) {
      if (nodeList[i].nodeType === Node.TEXT_NODE) {
        const splitText = nodeList[i].nodeValue.split(/\s/);
        splitText.forEach(piece => {
          content += `<span>${piece}</span> `;
        })
      } else {
        content += `<span>${nodeList[i].outerHTML}</span> `;
      }
    }
    
    document.getElementById('newExample').innerHTML = content;
    
    让k1=document.getElementById('Example').innerText;
    k1=k1.replace('my-own','my-own'))
    document.getElementById('Example').innerHTML=k1;
    让nodeList=document.getElementById('Example').childNodes;
    让内容=“”;
    for(设i=0;i{
    内容+=`${piece}`;
    })
    }否则{
    content+=`${nodeList[i].outerHTML}`;
    }
    }
    document.getElementById('newExample')。innerHTML=content;
    

    这里是一个沙盒,其中包含。
    innerText
    只获取文本,而不获取html。我更改文本的颜色,然后将其放回html。我错了吗?是的,因为这样你就做了
    innerText.split()
    ,失去了你刚才插入的跨度我明白你在告诉我什么,但我不知道如何解决它。无论如何,谢谢你的时间。这是一个很难解决的问题。要么使用
    innerText
    而丢失原有的HTML标记,要么使用
    innerHTML
    而必须处理属于标记本身的空格。取决于你想完成什么,你应该找到另一种方法。非常感谢你的关心,你详细的回答,尤其是你的时间。我已经测试了R Simoni的解决方案,效果非常好。杰出的贡献!!!谢谢你的好话!非常感谢您的解决方案。
    let k1 = document.getElementById('Example').innerText;
    k1 = k1.replace('my own', `<span class="color">my own</span>`)
    document.getElementById('Example').innerHTML = k1;
    
    let nodeList = document.getElementById('Example').childNodes;
    let content = '';
    for (let i = 0; i < nodeList.length; i++) {
      if (nodeList[i].nodeType === Node.TEXT_NODE) {
        const splitText = nodeList[i].nodeValue.split(/\s/);
        splitText.forEach(piece => {
          content += `<span>${piece}</span> `;
        })
      } else {
        content += `<span>${nodeList[i].outerHTML}</span> `;
      }
    }
    
    document.getElementById('newExample').innerHTML = content;