1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
|
---
title: element.innerHTML
slug: Web/API/Element/innerHTML
tags:
- Element.innerHTML
- Element.insertAdjacentHTML()
translation_of: Web/API/Element/innerHTML
---
<p>{{APIRef("DOM")}}</p>
<p><strong><code>Element.innerHTML</code></strong> 属性设置或获取HTML语法表示的元素的后代。</p>
<div class="note">
<p><strong>Note: </strong>如果一个 {{HTMLElement("div")}}, {{HTMLElement("span")}}, 或 {{HTMLElement("noembed")}} 节点有一个文本子节点,该节点包含字符 <code>(&),</code> <code>(<),</code> 或<code>(>)</code>, <code>innerHTML</code> 将这些字符分别返回为&amp;, &lt; 和 &gt; 。使用{{domxref("Node.textContent")}} 可获取一个这些文本节点内容的正确副本。</p>
</div>
<p>如果要向一个元素中插入一段 HTML,而不是替换它的内容,那么请使用 {{domxref("Element.insertAdjacentHTML", "insertAdjacentHTML()")}} 方法。</p>
<h2 id=".E8.AF.AD.E6.B3.95" name=".E8.AF.AD.E6.B3.95">语法</h2>
<pre class="brush: js">const content = element.innerHTML;
element.innerHTML = htmlString;
</pre>
<h3 id="值">值</h3>
<p>{{domxref("DOMString")}} 包含元素后代的HTML序列。设置元素的 <code>innerHTML</code> 将会删除所有该元素的后代并以上面给出的 htmlString 替代。</p>
<h3 id="例外">例外</h3>
<p><strong><code>SyntaxError</code> </strong></p>
<p> 当 HTML 没有被正确标记时,设置 <code>innerHTML</code> 将会抛出语法错误。</p>
<p><strong><code>NoModificationAllowedError</code> </strong></p>
<p> 当父元素是 {{domxref("Document")}} 时,设置 <code>innerHTML</code> 将会提示不允许修改。</p>
<h2 id="使用说明">使用说明</h2>
<p><code>innerHTML</code> 属性可以用来检查当前页面自最初加载到当前的 HTML 源码的变化。</p>
<h3 id="获取元素的HTML">获取元素的HTML</h3>
<p>获取 <code>innerHTML</code> 会导致用户代理序列化 由元素后代组成的 HTML 或者 XML 。返回结果字符串。</p>
<pre class="brush: js"><code>let contents = myElement.innerHTML;</code>
</pre>
<p>查看元素内容节点的 HTML 标记。</p>
<div class="note">
<p><strong>注</strong>:返回的 HTML 或者 XML 片段是基于当前元素的内容生成的,所以返回的标记和格式可能与原始页面的标记不匹配。</p>
</div>
<h3 id="替换元素的内容">替换元素的内容</h3>
<p>设置 <code>innerHTML</code> 的值可以让你轻松地将当前元素的内容替换为新的内容。</p>
<p>举个例子来说,你可以通过文档 {{domxref("Document.body", "body")}} 属性删除 body 的全部内容。</p>
<pre class="brush: js"><code>document.body.innerHTML = "";</code>
</pre>
<p>下面这个例子,首先获取文档当前的 HTML 标记并替换 <code>"<"</code> 字符为 HTML 实体 <code>"&lt;"</code>,从本质上来看,它是将 HTML 转换成原始文本,将其包裹在 {{HTMLElement("pre")}} 元素中。然后 <code>innerHTML</code> 的值被替换成新的字符串。最后,文档的内容被替换为页面显示源码。</p>
<pre class="brush: js"><code>document.documentElement.innerHTML = "<pre>" +
document.documentElement.innerHTML.replace(/</g,"&lt;") +
"</pre>";</code>
</pre>
<h4 id="其他:">其他:</h4>
<p>当给 <code>innerHTML</code> 设置一个值的时候到底发生了什么?用户代理按照以下步骤:</p>
<ol>
<li>给定的值被解析为 HTML 或者 XML (取决于文档类型),结果就是 {{domxref("DocumentFragment")}} 对象代表元素新设置的 DOM 节点。</li>
<li>如果元素内容被替换成 {{HTMLElement("template")}} 元素,<code><template></code> 元素的 {{domxref("HTMLTemplateElement.content", "content")}} 属性会被替换为步骤1中创建的新的 <code>DocumentFragment</code>。</li>
<li>对于其他所有元素,元素的内容都被替换为新的 <code>DocumentFragment</code>节点。</li>
</ol>
<h3 id="安全问题">安全问题</h3>
<p>用 <code>innerHTML</code> 插入文本到网页中并不罕见。但这有可能成为网站攻击的媒介,从而产生潜在的安全风险问题。</p>
<pre class="brush: js"><code>const name = "John";
// assuming 'el' is an HTML DOM element
el.innerHTML = name; // harmless in this case
// ...
name = "<script>alert('I am John in an annoying alert!')</script>";
el.innerHTML = name; // harmless in this case</code>
</pre>
<p>尽管这看上去像 {{interwiki("wikipedia", "cross-site scripting")}} 攻击,结果并不会导致什么。HTML 5 中指定不执行由 <code>innerHTML</code> 插入的 {{HTMLElement("script")}} 标签。</p>
<p>然而,有很多不依赖 {{HTMLElement("script")}} 标签去执行 JavaScript 的方式。所以当你使用<code>innerHTML</code> 去设置你无法控制的字符串时,这仍然是一个安全问题。例如:</p>
<pre class="brush: js"><code>const name = "<img src='x' onerror='alert(1)'>";
el.innerHTML = name; // shows the alert</code>
</pre>
<p>基于这个原因,当插入纯文本时,建议不要使用 <code>innerHTML</code> 。取而代之的是使用 {{domxref("Node.textContent")}} ,它不会把给定的内容解析为 HTML,它仅仅是将原始文本插入给定的位置。</p>
<div class="warning">
<p><strong>警告</strong>:如果你的项目将要经过各种形式的安全检查的话,使用 <code>innerHTML</code> 可能导致代码被拒绝。例如,如果你在<a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions">浏览器扩展</a>中<a href="https://wiki.mozilla.org/Add-ons/Reviewers/Guide/Reviewing#Step_2:_Automatic_validation">使用</a><a href="https://wiki.mozilla.org/Add-ons/Reviewers/Guide/Reviewing#Step_2:_Automatic_validation"> <code>innerHTML</code></a> 并将扩展提交到 <a href="https://addons.mozilla.org/">addons.mozilla.org</a> 的话,它将会在自动审核过程中被拒绝。</p>
</div>
<h2 id="例子">例子</h2>
<p>这个例子使用 <code>innerHTML</code> 创建一种机制用于将消息记录到网页上的框中。</p>
<h3 id="JavaScript">JavaScript</h3>
<pre class="brush: js"><code>function log(msg) {
var logElem = document.querySelector(".log");
var time = new Date();
var timeStr = time.toLocaleTimeString();
logElem.innerHTML += timeStr + ": " + msg + "<br/>";
}
log("Logging mouse events inside this container...");</code>
</pre>
<p>log() 函数通过 {{jsxref("Date")}} 对象的 {{jsxref("Date.toLocaleTimeString", "toLocaleTimeString()")}} 方法获取当前时间,然后将消息文本和时间戳放一起构建一个字符串,最后将其追加到具有 “log” 类的框上。</p>
<p>现在添加第二个方法:记录基于事件 (比如 {{event("mousedown")}}, {{event("click")}}, 和 {{event("mouseenter")}}) 的 {{domxref("MouseEvent")}} 的信息。</p>
<pre class="brush: js"><code>function logEvent(event) {
var msg = "Event <strong>" + event.type + "</strong> at <em>" +
event.clientX + ", " + event.clientY + "</em>";
log(msg);
}</code>
</pre>
<p>然后我们使用它作为包含我们消息的框上的鼠标事件的事件处理程序:</p>
<pre class="brush: js"><code>var boxElem = document.querySelector(".box");
boxElem.addEventListener("mousedown", logEvent);
boxElem.addEventListener("mouseup", logEvent);
boxElem.addEventListener("click", logEvent);
boxElem.addEventListener("mouseenter", logEvent);
boxElem.addEventListener("mouseleave", logEvent);</code>
</pre>
<h3 id="HTML">HTML</h3>
<p>这个例子的 HTML 代码就相当简洁了:</p>
<pre class="brush: html"><code><div class="box">
<div><strong>Log:</strong></div>
<div class="log"></div>
</div></code>
</pre>
<p>具有 “box” 类的 {{HTMLElement("div")}} 容器仅仅是出于布局考虑,用一个框来展示其内容。具有 “log” 类的 <div> 元素是作为消息本身的内容框。</p>
<h3 id="CSS">CSS</h3>
<p>下面是这个例子的 CSS:</p>
<pre class="brush: css"><code>.box {
width: 600px;
height: 300px;
border: 1px solid black;
padding: 2px 4px;
overflow-y: scroll;
overflow-x: auto;
}
.log {
margin-top: 8px;
font-family: monospace;
}</code>
</pre>
<h3 id="结果">结果</h3>
<p>结果就像下面展示的那样。你可以通过移动鼠标进出盒子,点击盒子等等来查看记录输出。</p>
<p>{{EmbedLiveSample("Example", 640, 350)}}</p>
<h2 id="规范">规范</h2>
<table class="standard-table">
<thead>
<tr>
<th scope="col">Specification</th>
<th scope="col">Status</th>
<th scope="col">Comment</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{SpecName('DOM Parsing', '#dom-element-innerhtml', 'Element.innerHTML')}}</td>
<td>{{Spec2('DOM Parsing')}}</td>
<td>Initial definition</td>
</tr>
</tbody>
</table>
<h2 id="浏览器兼容性">浏览器兼容性</h2>
<p>{{Compat("api.Element.innerHTML")}}</p>
<h2 id="相关链接">相关链接</h2>
<ul>
<li>{{domxref("Node.textContent")}} and {{domxref("Node.innerText")}}</li>
<li>{{domxref("Element.insertAdjacentHTML()")}}</li>
<li>Parsing HTML into a DOM tree: {{domxref("DOMParser")}}</li>
<li>Serializing XML or HTML into a DOM tree: {{domxref("XMLSerializer")}}</li>
</ul>
|