Div innerText 在将显示设置为 none 后丢失新行
Div innerText loses new lines after setting display to none
在编写基于自定义所见即所得 HTML 的编辑器时,我遇到了这种奇怪的行为。
在 div 中输入一些包含新行的文本,contentEditable
设置为 true
。
此时 div.innerText
完全包含输入的文本,包括新行。
然后设置div.style.display = none
并重新检查div.innerText
:它是相同的文本,但是新行被删除了。
这是为什么?这种情况有“标准行为”吗?
(在 FF Developer Edition 89.0b3(64 位)和 Chrome 版本 90.0.4430.85(官方构建)(64 位)中测试)
=>跟进
还有一个类似的奇怪问题:
var d = document.getElementById("divTest")
function setup() {
d.innerText = "1\n2"
}
function log() {
console.log(d.innerText)
logChildren()
}
function logChildren() {
console.log("Child nodes: ");
d.childNodes.forEach(node => {
console.log(node.toString());
});
}
div[contenteditable] {
border: 1px solid red;
}
<div contenteditable="true" id="divTest"></div>
<input type="button" value="setContent" onclick="setup()"/>
<input type="button" value="log" onclick="log()"/>
单击 setContent
按钮,然后单击 log
按钮。输出符合预期:
1
2
[object Text]
[object HTMLBRElement]
[object Text]
然后在输入里面点击div。在 2 后按 enter 转到新行,然后按 3。一个得到
1
2
3
在 div 中,人们希望在 div.innerText
中得到相同的结果,但不幸的是:
1
2
3
Child nodes:
[object Text]
[object HTMLBRElement]
[object HTMLDivElement]
[object HTMLDivElement]
为什么 1 是 [object Text]
而 2 和 3 [object HTMLDivElement]
?为什么1和2之间会有空行?等...
对我来说没有任何意义。
innerText
的实现取决于元素是否可见。正如@Nisala 在评论中指出的那样,如果将 div
的 display
属性设置回 block
,innerText
将再次包含换行符。
const input = document.querySelector("#input");
function performExperiment() {
console.log(`innerText before style change: ${input.innerText}`);
input.style.display = "none";
console.log(`innerText after first style change: ${input.innerText}`);
input.style.display = "block";
console.log(`innerText after second style change: ${input.innerText}`);
}
#input {
border: 1px solid black;
}
<p>Enter multiple lines of text into the box below, then click the button</p>
<div id="input" contenteditable="true"></div>
<button onclick="performExperiment()">Experiment</button>
如果我们看一下 innerText
documentation,我们会看到 getter 行为的第一步定义如下:
- If this is not being rendered or if the user agent is a non-CSS user agent, then return this's descendant text content.
Note: This step can produce suprising results, as when the innerText
getter is invoked on an element not being rendered, its text contents are returned, but when accessed on an element that is being rendered, all of its children that are not being rendered have their text contents ignored.
所以当我们的 div
没有被渲染时,我们应该期望 innerText
returns 我们的 div
的 textContent
。的确,这就是我们所看到的。
const input = document.querySelector("#input");
function performExperiment() {
input.style.display = "none";
console.log(`innerText: ${input.innerText}`);
console.log(`textContent: ${input.textContent}`);
}
#input {
border: 1px solid black;
}
<p>Enter multiple lines of text into the box below, then click the button</p>
<div id="input" contenteditable="true"></div>
<button onclick="performExperiment()">Experiment</button>
那么,当 div
可见时,为什么我们的 innerText
中会出现换行符?文档继续:
- Let current be the list resulting in running the inner text collection steps with node. Each item in results will either be a string or a positive integer (a required line break count).
在这种情况下,innerText
将忽略 textContent
,而是对 childNodes
列表进行操作。让我们看看它对我们的 div
:
有什么价值
const input = document.querySelector("#input");
function performExperiment() {
input.childNodes.forEach(node => {
console.log(node.toString());
});
}
#input {
border: 1px solid black;
}
<p>Enter multiple lines of text into the box below, then click the button</p>
<div id="input" contenteditable="true"></div>
<button onclick="performExperiment()">Experiment</button>
如您所见,按 ENTER
键通过 添加一个 div 来为我们的 div 的内容添加一个换行符div
的 childNodes 列表。为什么会出现这种情况超出了这个问题的范围,但它本身就是一个很好的问题。
如果您正在使用页内编辑器,HTML 规范 has a section containing best practices。
回顾一下:
如果div
可见,则innerText
getter使用div
的textContent
属性。
如果 div
不可见,则 childNodes
树中的每个节点都遵循 inner text collection steps,并将结果连接在一起。
在为我们的 div
计算 innerText
的值时,display
属性的值很重要,因为它决定 textContent
属性 或将使用 childNodes
树的评估。
注意:@Domino 在 中提供了更多信息。
在编写基于自定义所见即所得 HTML 的编辑器时,我遇到了这种奇怪的行为。
在 div 中输入一些包含新行的文本,contentEditable
设置为 true
。
此时 div.innerText
完全包含输入的文本,包括新行。
然后设置div.style.display = none
并重新检查div.innerText
:它是相同的文本,但是新行被删除了。
这是为什么?这种情况有“标准行为”吗?
(在 FF Developer Edition 89.0b3(64 位)和 Chrome 版本 90.0.4430.85(官方构建)(64 位)中测试)
=>跟进 还有一个类似的奇怪问题:
var d = document.getElementById("divTest")
function setup() {
d.innerText = "1\n2"
}
function log() {
console.log(d.innerText)
logChildren()
}
function logChildren() {
console.log("Child nodes: ");
d.childNodes.forEach(node => {
console.log(node.toString());
});
}
div[contenteditable] {
border: 1px solid red;
}
<div contenteditable="true" id="divTest"></div>
<input type="button" value="setContent" onclick="setup()"/>
<input type="button" value="log" onclick="log()"/>
单击 setContent
按钮,然后单击 log
按钮。输出符合预期:
1
2
[object Text]
[object HTMLBRElement]
[object Text]
然后在输入里面点击div。在 2 后按 enter 转到新行,然后按 3。一个得到
1
2
3
在 div 中,人们希望在 div.innerText
中得到相同的结果,但不幸的是:
1
2
3
Child nodes:
[object Text]
[object HTMLBRElement]
[object HTMLDivElement]
[object HTMLDivElement]
为什么 1 是 [object Text]
而 2 和 3 [object HTMLDivElement]
?为什么1和2之间会有空行?等...
对我来说没有任何意义。
innerText
的实现取决于元素是否可见。正如@Nisala 在评论中指出的那样,如果将 div
的 display
属性设置回 block
,innerText
将再次包含换行符。
const input = document.querySelector("#input");
function performExperiment() {
console.log(`innerText before style change: ${input.innerText}`);
input.style.display = "none";
console.log(`innerText after first style change: ${input.innerText}`);
input.style.display = "block";
console.log(`innerText after second style change: ${input.innerText}`);
}
#input {
border: 1px solid black;
}
<p>Enter multiple lines of text into the box below, then click the button</p>
<div id="input" contenteditable="true"></div>
<button onclick="performExperiment()">Experiment</button>
如果我们看一下 innerText
documentation,我们会看到 getter 行为的第一步定义如下:
- If this is not being rendered or if the user agent is a non-CSS user agent, then return this's descendant text content.
Note: This step can produce suprising results, as when the
innerText
getter is invoked on an element not being rendered, its text contents are returned, but when accessed on an element that is being rendered, all of its children that are not being rendered have their text contents ignored.
所以当我们的 div
没有被渲染时,我们应该期望 innerText
returns 我们的 div
的 textContent
。的确,这就是我们所看到的。
const input = document.querySelector("#input");
function performExperiment() {
input.style.display = "none";
console.log(`innerText: ${input.innerText}`);
console.log(`textContent: ${input.textContent}`);
}
#input {
border: 1px solid black;
}
<p>Enter multiple lines of text into the box below, then click the button</p>
<div id="input" contenteditable="true"></div>
<button onclick="performExperiment()">Experiment</button>
那么,当 div
可见时,为什么我们的 innerText
中会出现换行符?文档继续:
- Let current be the list resulting in running the inner text collection steps with node. Each item in results will either be a string or a positive integer (a required line break count).
在这种情况下,innerText
将忽略 textContent
,而是对 childNodes
列表进行操作。让我们看看它对我们的 div
:
const input = document.querySelector("#input");
function performExperiment() {
input.childNodes.forEach(node => {
console.log(node.toString());
});
}
#input {
border: 1px solid black;
}
<p>Enter multiple lines of text into the box below, then click the button</p>
<div id="input" contenteditable="true"></div>
<button onclick="performExperiment()">Experiment</button>
如您所见,按 ENTER
键通过 添加一个 div 来为我们的 div 的内容添加一个换行符div
的 childNodes 列表。为什么会出现这种情况超出了这个问题的范围,但它本身就是一个很好的问题。
如果您正在使用页内编辑器,HTML 规范 has a section containing best practices。
回顾一下:
如果div
可见,则innerText
getter使用div
的textContent
属性。
如果 div
不可见,则 childNodes
树中的每个节点都遵循 inner text collection steps,并将结果连接在一起。
在为我们的 div
计算 innerText
的值时,display
属性的值很重要,因为它决定 textContent
属性 或将使用 childNodes
树的评估。
注意:@Domino 在