我创建了一个单词计数功能,并发现了一个不一致的地方。它产生了不同的结果,计算html中的文本单词取决于html中的元素是否是document.body的一部分。例如:
html = "<div>Line1</div><div>Line2<br></div>";
document.body.insertAdjacentHTML("afterend", '<div id="node1"></div>');
node1 = document.getElementById("node1");
node1.style.whiteSpace = 'pre-wrap';
node1.innerHTML = html;
node2 = document.createElement('div');
node2.style.whiteSpace = 'pre-wrap';
node2.innerHTML = html;
应用white-space: pre-wrap
样式,使html变量中的代码在浏览器之间一致地以换行方式呈现。在上述情况中:
node1.innerText // is "Line1\nLine2\n" which counts as two words.
node2.innerText // is "Line1Line2" which counts as only one word.
我的字数功能是:
function countWords(s) {
s = (s+' ').replace(/^\s+/g, ''); // remove leading whitespace only
s = s.replace(/\s/g, ' '); // change all whitespace to spaces
s = s.replace(/[ ]{2,}/gi,' ')+' '; // change 2 or more spaces to 1
return s.split(' ').filter(String).length;
}
如果我在网络控制台中做了这样的事情:node1.after(node2);
node2.innerText // is changed to "Line1\nLine2\n" which counts as two words.
我的问题是:
white-space: pre-wrap
样式在插入到node 2.innerText
之前没有应用到document.body中?node 2
必须是document.body的一部分才能获得white-space: pre-wrap
样式的node 2.innerText
值,那么我如何做到这一点而不必使node 2
可见?createElement
设置节点元素时,该节点元素驻留在哪里?它似乎不能在<html>
标记内外的Web检查器中查看,而且我无法在document对象中找到它。这使我意识到,这种差异与节点元素是否在document.body:javascript createElement(),样式问题有关。
发布于 2022-05-23 07:21:21
作为对上述问题的跟进,我需要计算html文本字符串中的单词,如:<div>Line1</div><div>Line2<br></div>
,其中单词计数与在显示的DOM中呈现的html匹配。
概括地说,当您使用createElement
创建一个元素时,它还没有插入到DOM中,在检查DOM时也找不到。在元素插入DOM之前,CSS属性是存在的,但是没有执行,因此没有呈现。当元素插入到DOM中时,将执行CSS属性,并根据CSS呈现该元素。
下面是我最后使用的html字符串到呈现的html文本函数。该函数去掉html标记,但保留“空白”,这样就可以计算单词(包括IE 11在内的浏览器之间的一致性)。
var html = "<div>Line1</div><div>Line2<br></div>";
// Display the html string
var htmlts = document.getElementById("htmlts");
htmlts.innerText = html;
// Display a DOM render of the html string
var node1 = document.getElementById("node1");
node1.style.whiteSpace = 'pre-wrap';
node1.innerHTML = html;
// Display the innerText of the above DOM render
var node1ts = document.getElementById("node1ts");
node1ts.innerText = node1.innerText;
// Display the results of the htmlToText function
var node2ts = document.getElementById("node2ts");
node2ts.innerText = htmlToText(html);
// Adapted from https://stackoverflow.com/a/39157530
function htmlToText(html) {
var temp = document.createElement('div');
temp.style.whiteSpace = 'pre-wrap';
temp.style.position = "fixed"; // Overlays the normal flow
temp.style.left = "0"; // Placed flush left
temp.style.top = "0"; // Placed at the top
temp.style.zIndex = "-999"; // Placed under other elements
// opacity = "0" works for the entire temp element, even in IE 11.
temp.style.opacity = "0"; // Everything transparent
temp.innerHTML = html; // Render the html string
document.body.parentNode.appendChild(temp); // Places just before </html>
var out = temp.innerText;
// temp.remove(); // Throws an error in IE 11
// Solution from https://stackoverflow.com/a/27710003
temp.parentNode.removeChild(temp); // Removes the temp element
return out;
}
<html lang="en-US">
<body>
HTML String: <code id="htmlts"></code><br><br>
Visible Render of HTML String (for comparison): <div id="node1"></div><br>
Visible Render Text String: <code id="node1ts"></code><br>
Function Returned Text String: <Code id="node2ts"></code><br>
</body>
</html>
如果您希望在body元素中插入临时元素,请将document.body.parentNode.appendChild
更改为document.body.appendChild
。
正如诺姆所建议的,您也可以使用temp.style.top = "-1000px";
。
为了回答我的好奇问题:在元素“插入DOM”之前,它似乎位于一个类似于阴影DOM或Shadow的空间中。
https://stackoverflow.com/questions/70911131
复制相似问题