aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/web/web_components
diff options
context:
space:
mode:
authorPeter Bengtsson <mail@peterbe.com>2020-12-08 14:40:17 -0500
committerPeter Bengtsson <mail@peterbe.com>2020-12-08 14:40:17 -0500
commit33058f2b292b3a581333bdfb21b8f671898c5060 (patch)
tree51c3e392513ec574331b2d3f85c394445ea803c6 /files/zh-cn/web/web_components
parent8b66d724f7caf0157093fb09cfec8fbd0c6ad50a (diff)
downloadtranslated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.gz
translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.bz2
translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.zip
initial commit
Diffstat (limited to 'files/zh-cn/web/web_components')
-rw-r--r--files/zh-cn/web/web_components/html导入/index.html61
-rw-r--r--files/zh-cn/web/web_components/index.html215
-rw-r--r--files/zh-cn/web/web_components/status_in_firefox/index.html51
-rw-r--r--files/zh-cn/web/web_components/using_custom_elements/index.html253
-rw-r--r--files/zh-cn/web/web_components/using_shadow_dom/index.html221
-rw-r--r--files/zh-cn/web/web_components/using_templates_and_slots/index.html334
-rw-r--r--files/zh-cn/web/web_components/影子_dom/index.html90
7 files changed, 1225 insertions, 0 deletions
diff --git a/files/zh-cn/web/web_components/html导入/index.html b/files/zh-cn/web/web_components/html导入/index.html
new file mode 100644
index 0000000000..fe3aeb99cd
--- /dev/null
+++ b/files/zh-cn/web/web_components/html导入/index.html
@@ -0,0 +1,61 @@
+---
+title: HTML 导入(HTML Imports)
+slug: Web/Web_Components/HTML导入
+tags:
+ - HTML Imports
+ - Web Components
+translation_of: Web/Web_Components/HTML_Imports
+---
+<p>{{DefaultAPISidebar("Web Components")}}</p>
+
+<div class="blockIndicator obsolete">
+<p><strong>在 Google Chrome 73 后已过时</strong><br>
+ 此功能已过时。虽然它可能仍然适用于某些浏览器,但不鼓励使用它,因为它随时可能被删除。尽量避免使用它。</p>
+</div>
+
+<div class="warning">
+<p>Firefox 将不会以当前形式发布HTML导入特性,<font><font>有关</font><font> 更多信息,</font><font>请参阅此</font></font><a href="https://hacks.mozilla.org/2015/06/the-state-of-web-components/" rel="noopener"><font><font>状态更新</font></font></a>。<font><font>在对标准达成共识或制定替代机制之前,您可以使用Google等的polyfill </font></font><code><a href="https://github.com/webcomponents/webcomponentsjs" rel="noopener">webcomponents.js</a></code><font><font>。</font></font> </p>
+</div>
+
+<p><strong>HTML Imports </strong>旨在成为 <a href="/zh-CN/docs/Web/Web_Components">Web Components</a> 的打包机制,但也可以单独使用 HTML Imports。</p>
+
+<div>可以在HTML文档中使用<code><a href="/en-US/docs/Web/HTML/Element/link">&lt;link&gt;</a></code> 标记导入HTML文件,如下所示:</div>
+
+<div> </div>
+
+<pre>&lt;link rel="import" href="myfile.html"&gt;</pre>
+
+<p><span style="line-height: 1.5;">链接类型 </span><code style="font-style: normal; line-height: 1.5;">import</code><span style="line-height: 1.5;"> 是新加入的。</span></p>
+
+<h2 id="规范">规范</h2>
+
+<table class="spec-table standard-table">
+ <tbody>
+ <tr>
+ <th scope="col">规范</th>
+ <th scope="col">状态</th>
+ <th scope="col">评论</th>
+ </tr>
+ <tr>
+ <td>{{SpecName('HTML Imports', "", "")}}</td>
+ <td>{{Spec2('HTML Imports')}}</td>
+ <td>初步定义</td>
+ </tr>
+ </tbody>
+</table>
+
+<h2 id="浏览器兼容性"><font><font>浏览器兼容性</font></font></h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("html.elements.link.rel.import")}}</p>
+
+<h2 id="阅读更多"><strong>阅读更多:</strong></h2>
+
+<ul>
+ <li>https://developer.mozilla.org/zh-CN/docs/Web/Web_Components</li>
+ <li>https://developer.mozilla.org/zh-CN/docs/Web/Web_Components/Custom_Elements</li>
+ <li>https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/template</li>
+ <li>https://developer.mozilla.org/zh-CN/docs/Web/Web_Components/Shadow_DOM<br>
+  </li>
+</ul>
diff --git a/files/zh-cn/web/web_components/index.html b/files/zh-cn/web/web_components/index.html
new file mode 100644
index 0000000000..bb6c25179f
--- /dev/null
+++ b/files/zh-cn/web/web_components/index.html
@@ -0,0 +1,215 @@
+---
+title: Web Components
+slug: Web/Web_Components
+tags:
+ - Landing
+ - Web Components
+translation_of: Web/Web_Components
+---
+<div>{{DefaultAPISidebar("Web Components")}}</div>
+
+<div class="summary">
+<p>Web Components 是一套不同的技术,允许您创建可重用的定制元素(它们的功能封装在您的代码之外)并且在您的web应用中使用它们。</p>
+</div>
+
+<h2 id="概念和使用">概念和使用</h2>
+
+<p>作为开发者,我们都知道尽可能多的重用代码是一个好主意。这对于自定义标记结构来说通常不是那么容易 — 想想复杂的HTML(以及相关的样式和脚本),有时您不得不写代码来呈现自定义UI控件,并且如果您不小心的话,多次使用它们会使您的页面变得一团糟。</p>
+
+<p>Web Components旨在解决这些问题 — 它由三项主要技术组成,它们可以一起使用来创建封装功能的定制元素,可以在你喜欢的任何地方重用,不必担心代码冲突。</p>
+
+<ul>
+ <li><strong>Custom elements(自定义元素):</strong>一组JavaScript API,允许您定义custom elements及其行为,然后可以在您的用户界面中按照需要使用它们。</li>
+ <li><strong>Shadow DOM(影子DOM)</strong>:一组JavaScript API,用于将封装的“影子”DOM树附加到元素(与主文档DOM分开呈现)并控制其关联的功能。通过这种方式,您可以保持元素的功能私有,这样它们就可以被脚本化和样式化,而不用担心与文档的其他部分发生冲突。</li>
+ <li><strong>HTML templates(HTML模板):</strong> {{HTMLElement("template")}} 和 {{HTMLElement("slot")}} 元素使您可以编写不在呈现页面中显示的标记模板。然后它们可以作为自定义元素结构的基础被多次重用。</li>
+</ul>
+
+<p>实现web component的基本方法通常如下所示:</p>
+
+<ol>
+ <li>创建一个类或函数来指定web组件的功能,如果使用类,请使用 ECMAScript 2015 的类语法(参阅<a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes">类</a>获取更多信息)。</li>
+ <li>使用 {{domxref("CustomElementRegistry.define()")}} 方法注册您的新自定义元素 ,并向其传递要定义的元素名称、指定元素功能的类、以及可选的其所继承自的元素。</li>
+ <li>如果需要的话,使用{{domxref("Element.attachShadow()")}} 方法将一个shadow DOM附加到自定义元素上。使用通常的DOM方法向shadow DOM中添加子元素、事件监听器等等。</li>
+ <li>如果需要的话,使用 {{htmlelement("template")}} 和{{htmlelement("slot")}} 定义一个HTML模板。再次使用常规DOM方法克隆模板并将其附加到您的shadow DOM中。</li>
+ <li>在页面任何您喜欢的位置使用自定义元素,就像使用常规HTML元素那样。</li>
+</ol>
+
+<h2 id="教程">教程</h2>
+
+<dl>
+ <dt><a href="/zh-CN/docs/Web/Web_Components/Using_custom_elements">Using custom elements</a></dt>
+ <dd>介绍如何使用自定义元素的功能来创建简单的 web components,以及生命周期回调和其他更高级的功能。</dd>
+ <dt><a href="/zh-CN/docs/Web/Web_Components/Using_shadow_DOM">Using shadow DOM</a></dt>
+ <dd>介绍 shadow DOM 的基础知识,展示如何向元素中附加shadow DOM,添加到shadow DOM树,添加样式等等。</dd>
+ <dt><a href="/zh-CN/docs/Web/Web_Components/Using_templates_and_slots">Using templates and slots</a></dt>
+ <dd>介绍如何使用{{htmlelement("template")}} 和 {{htmlelement("slot")}} 元素定义可重用的HTML结构,然后在Web components中使用该结构。</dd>
+</dl>
+
+<h2 id="参考">参考</h2>
+
+<h3 id="Custom_elements">Custom elements</h3>
+
+<dl>
+ <dt>{{domxref("CustomElementRegistry")}}</dt>
+ <dd>包含自定义元素相关功能,最值得注意的是 {{domxref("CustomElementRegistry.define()")}} 方法用来注册新的自定义元素,这样就可以在文档中使用它们。</dd>
+ <dt>{{domxref("Window.customElements")}}</dt>
+ <dd>返回 <code>CustomElementRegistry</code> 对象的引用。</dd>
+ <dt><a href="https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements#Using_the_lifecycle_callbacks">生命周期回调</a></dt>
+ <dd>定义在自定义元素的类定义中的特殊回调函数,影响其行为:
+ <ul>
+ <li><code>connectedCallback</code>: 当自定义元素第一次被连接到文档DOM时被调用。</li>
+ <li><code>disconnectedCallback</code>: 当自定义元素与文档DOM断开连接时被调用。</li>
+ <li><code>adoptedCallback</code>: 当自定义元素被移动到新文档时被调用。</li>
+ <li><code>attributeChangedCallback</code>: 当自定义元素的一个属性被增加、移除或更改时被调用。</li>
+ </ul>
+ </dd>
+ <dd>
+ <ul>
+ </ul>
+ </dd>
+</dl>
+
+<dl>
+ <dt>创建自定义内置元素的扩展</dt>
+ <dd>
+ <ul>
+ <li>{{htmlattrxref("is")}} 全局 HTML 属性:允许您指定一个标准HTML元素应该表现得像一个已注册的自定义内置元素。</li>
+ <li>{{domxref("Document.createElement()")}} 方法的“is”选项:允许您创建一个标准HTML元素的实例,表现得像一个给定的已注册的自定义内置元素。</li>
+ </ul>
+ </dd>
+ <dt>CSS 伪类</dt>
+ <dd>与自定义元素特别相关的伪类:
+ <ul>
+ <li>{{cssxref(":defined")}}: 匹配任何已定义的元素,包括内置元素和使用<code>CustomElementRegistry.define()</code>定义的自定义元素。</li>
+ <li>{{cssxref(":host")}}: 选择 <a href="/en-US/docs/Web/Web_Components/Using_shadow_DOM">shadow DOM </a>的 shadow host ,内容是它内部使用的 CSS( containing the CSS it is used inside )。</li>
+ <li>{{cssxref(":host()")}}: 选择 <a href="/en-US/docs/Web/Web_Components/Using_shadow_DOM">shadow DOM </a>的 shadow host ,内容是它内部使用的 CSS (这样您可以从 shadow DOM 内部选择自定义元素)— 但只匹配给定方法的选择器的 shadow host 元素。</li>
+ <li>{{cssxref(":host-context()")}}: 选择 <a href="/en-US/docs/Web/Web_Components/Using_shadow_DOM">shadow DOM </a>的 shadow host ,内容是它内部使用的 CSS (这样您可以从 shadow DOM 内部选择自定义元素)— 但只匹配给定方法的选择器匹配元素的子 shadow host 元素。</li>
+ </ul>
+ </dd>
+</dl>
+
+<h3 id="Shadow_DOM">Shadow DOM</h3>
+
+<dl>
+ <dt>{{domxref("ShadowRoot")}}</dt>
+ <dd>表示shadow DOM子树的根节点。</dd>
+ <dt>{{domxref("DocumentOrShadowRoot")}}</dt>
+ <dd>定义了可在文档和shadow根中使用的功能的mixin。</dd>
+ <dt>{{domxref("Element")}} extensions</dt>
+ <dd>与shadow DOM有关的<code>Element</code> 接口的扩展:
+ <ul>
+ <li>{{domxref("Element.attachShadow()")}} 方法将shadow DOM树附加给特定元素。</li>
+ <li>{{domxref("Element.shadowRoot")}} 属性返回附加给特定元素的shadow root,或者 <code>null</code> 如果没有shadow root被附加。</li>
+ </ul>
+ </dd>
+ <dt>{{domxref("Node")}} 相关拓展</dt>
+ <dd>与 shadow DOM 相关的 <code>Node</code> 接口的拓展:
+ <ul>
+ <li>{{domxref("Node.getRootNode()")}} 方法返回上下文对象的根,可以选择包含shadow root,如果可用的话。</li>
+ <li>{{domxref("Node.isConnected")}} 属性返回一个布尔值表示节点是否连接(直接或间接)到上下文对象。例如,在普通DOM的情况下为{{domxref("Document")}} 对象,或者在shadow DOM的情况下为 {{domxref("ShadowRoot")}} 。</li>
+ </ul>
+ </dd>
+ <dt>{{domxref("Event")}} 拓展</dt>
+ <dd>与shadow DOM相关的<code>Event</code> 接口的扩展:</dd>
+ <dd>
+ <ul>
+ <li>{{domxref("Event.composed")}}: 返回 {{jsxref("Boolean")}} 它表明事件是否会通过shadow DOM边界传播到标准DOM。</li>
+ <li>返回事件的路径(侦听器将被调用的对象)。如果shadow root是使用{{domxref("ShadowRoot.mode")}}为closed创建的,则不包括shadow树中的节点。</li>
+ </ul>
+ </dd>
+</dl>
+
+<h3 id="HTML_templates">HTML templates</h3>
+
+<dl>
+ <dt>{{htmlelement("template")}}</dt>
+ <dd>包含一个HTML片段,不会在文档初始化时渲染。但是可以在运行时使用JavaScript显示。主要用作自定义元素结构的基础。关联的DOM接口是{{domxref("HTMLTemplateElement")}}。</dd>
+ <dt>{{htmlelement("slot")}}</dt>
+ <dd>web component中的一个占位符,你可以填充自己的标记,这样你就可以创建单独的DOM树并将它们呈现在一起。关联的DOM接口是{{domxref("HTMLSlotElement")}}。</dd>
+ <dt>The <code><a href="/en-US/docs/Web/HTML/Global_attributes/slot">slot</a></code> global HTML attribute</dt>
+ <dd>将在shadow DOM树中的插槽分配给一个元素。</dd>
+ <dt>{{domxref("Slotable")}}</dt>
+ <dd>由 {{domxref("Element")}} 和 {{domxref("Text")}} 节点实现的mixin,定义了允许它们成为 {{htmlelement("slot")}} 元素内容的特性。mixin定义了一个属性, {{domxref("Slotable.assignedSlot")}},返回节点所插入的插槽的引用。</dd>
+</dl>
+
+<dl>
+ <dt>{{domxref("Element")}} extensions</dt>
+ <dd>与插槽相关的<code>Element</code>接口的扩展:
+ <ul>
+ <li>{{domxref("Element.slot")}}: 返回附加到元素上的shadow DOM插槽的名字。</li>
+ </ul>
+ </dd>
+ <dt>CSS pseudo-elements</dt>
+ <dd>slots特别相关的伪元素:
+ <ul>
+ <li>{{cssxref("::slotted")}}: 匹配任何已经插入一个slot的内容。</li>
+ </ul>
+ </dd>
+ <dt>The {{event("slotchange")}} event</dt>
+ <dd>当插槽中的节点改变时在 {{domxref("HTMLSlotElement")}} 实例(<a href="https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/slot" title="HTML &lt;slot> element—是 Web Components 技术的一部分,是自定义web组件的占位符,目的是分离创建DOM树和DOM树的表现()。"><code>&lt;slot&gt;</code></a> 元素)上触发。</dd>
+</dl>
+
+<h2 id="例子">例子</h2>
+
+<p>在 <a href="https://github.com/mdn/web-components-examples">web-components-examples</a>,我们正在构建一些例子。以后会添加更多。</p>
+
+<h2 id="规范">规范</h2>
+
+<table class="standard-table">
+ <tbody>
+ <tr>
+ <th scope="col">Specification</th>
+ <th scope="col">Status</th>
+ <th scope="col">Comment</th>
+ </tr>
+ <tr>
+ <td>{{SpecName("HTML WHATWG","scripting.html#the-template-element","&lt;template&gt; element")}}</td>
+ <td>{{Spec2("HTML WHATWG")}}</td>
+ <td>The definition of {{HTMLElement("template")}}.</td>
+ </tr>
+ <tr>
+ <td>{{SpecName("HTML WHATWG","custom-elements.html#custom-elements","custom elements")}}</td>
+ <td>{{Spec2("HTML WHATWG")}}</td>
+ <td>The definition of <a href="/en-US/docs/Web/Web_Components/Using_custom_elements">HTML Custom Elements</a>.</td>
+ </tr>
+ <tr>
+ <td>{{SpecName("DOM WHATWG","#shadow-trees","shadow trees")}}</td>
+ <td>{{Spec2("DOM WHATWG")}}</td>
+ <td>The definition of <a href="/en-US/docs/Web/Web_Components/Using_shadow_DOM">Shadow DOM</a>.</td>
+ </tr>
+ <tr>
+ <td>{{SpecName("HTML Imports", "", "")}}</td>
+ <td>{{Spec2("HTML Imports")}}</td>
+ <td>Initial <a href="/en-US/docs/Web/Web_Components/HTML_Imports">HTML Imports</a> definition.</td>
+ </tr>
+ <tr>
+ <td>{{SpecName("Shadow DOM", "", "")}}</td>
+ <td>{{Spec2("Shadow DOM")}}</td>
+ <td>Initial <a href="/en-US/docs/Web/Web_Components/Using_shadow_DOM">Shadow DOM</a> definition.</td>
+ </tr>
+ </tbody>
+</table>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p>通常来说:</p>
+
+<ul>
+ <li>Firefox(版本63)、Chrome和Opera都默认支持Web组件。</li>
+ <li>Safari支持许多web组件特性,但比上述浏览器少。</li>
+ <li>Edge正在开发一个实现。</li>
+</ul>
+
+<p>要获得特定特性的详细浏览器支持,您必须参考上面列出的参考页面。</p>
+
+<h2 id="另见">另见</h2>
+
+<ul>
+ <li><a href="https://www.webcomponents.org/">webcomponents.org</a> — site featuring web components examples, tutorials, and other information.</li>
+ <li><a href="https://github.com/hybridsjs/hybrids">Hybrids</a> — Open source web components library, which favors plain objects and pure functions over <code>class</code> and <font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">this</span></font> syntax. It provides a simple and functional API for creating custom elements.</li>
+ <li><a href="https://www.polymer-project.org/">Polymer</a> — Google's web components framework — a set of polyfills, enhancements, and examples. Currently the easiest way to use web components cross-browser.</li>
+ <li><a href="https://github.com/devpunks/snuggsi#readme">Snuggsi.es</a> — Easy Web Components in ~1kB <em>Including polyfill</em> — All you need is a browser and basic understanding of HTML, CSS, and JavaScript classes to be productive.</li>
+ <li><a href="https://github.com/slimjs/slim.js">Slim.js</a> — Open source web components library — a high-performant library for rapid and easy component authoring; extensible and pluggable and cross-framework compatible.</li>
+ <li><a href="https://www.htmlelements.com/">Smart.js</a> — Web Components library with simple API for creating cross-browser custom elements.</li>
+ <li><a href="https://stenciljs.com/">Stencil</a> — Toolchain for building reusable, scalable design systems in web components.</li>
+</ul>
diff --git a/files/zh-cn/web/web_components/status_in_firefox/index.html b/files/zh-cn/web/web_components/status_in_firefox/index.html
new file mode 100644
index 0000000000..d57e5adef5
--- /dev/null
+++ b/files/zh-cn/web/web_components/status_in_firefox/index.html
@@ -0,0 +1,51 @@
+---
+title: Status of Web Components support in Firefox
+slug: Web/Web_Components/Status_in_Firefox
+translation_of: Web/Web_Components/Status_in_Firefox
+---
+<p>{{DefaultAPISidebar("Web Components")}}{{SeeCompatTable}}</p>
+
+<p><a href="/en-US/docs/Web/Web_Components">Web Components</a> 依旧是一项非常新的技术,它的规范正随着浏览器的实现而不断演变并且 Web 开发者正在测试和使用它。 它的实现状态是变化的并且演变的十分迅速; 这篇文章列出了在 <a href="/en-US/docs/Mozilla/Gecko">Gecko</a> 上的状态, 用于 Firefox 和Firefox OS.</p>
+
+<div class="blob instapaper_body" id="readme">
+<article class="markdown-body entry-content">
+<h2 id="原生支持">原生支持</h2>
+
+<p>下面的特征已经被实现了并且默认在 Firefox and Firefox OS 中被激活:</p>
+
+<ul>
+ <li>{{HTMLElement("template")}}</li>
+</ul>
+
+<h2 id="即将到来的特征">即将到来的特征</h2>
+
+<ul>
+ <li>一个实现关于新的 <a href="/en-US/docs/Web/Web_Components/Shadow_DOM">Shadow DOM</a> 共识有望在2016年第一季度达成; <a href="https://annevankesteren.nl/2015/07/shadow-dom-custom-elements-update">Anne's</a> 和 <a href="https://hacks.mozilla.org/2015/06/the-state-of-web-components/">Wilson's</a> 的博客讲述了这些细节。 这依然有 <a href="https://github.com/w3c/webcomponents/labels/shadow-dom">大量的讨论和公开问题</a> 关于这个规范.。并且所有的浏览器实现被有望在未来得到更新.</li>
+ <li><strong>自定义元素</strong> 是从头开始, 用一种方式来重建它们使用 ECMAScript 6 “class” 语法 (换而言之, 更少的使用基于原型的语法). 苹果公司的 Ryosuke Niwa 正在填补某些实验性功能使用新的途径.
+ <ul>
+ <li>旧的语法将可以与新的语法一起在Chrome 中工作一段时间(例如, {{domxref("Element.createShadowRoot()")}} 对应 {{domxref("Element.attachShadow()")}}), 但不能原生的在Firefox中工作。</li>
+ </ul>
+ </li>
+ <li>这将会有一个供应商 <a href="https://github.com/w3c/WebPlatformWG/blob/gh-pages/meetings/29janWC.md">面对面交流的机会在2016年一月</a> 来讨论问来会出现的问题 。</li>
+</ul>
+
+<h2 id="被摒弃的功能">被摒弃的功能</h2>
+
+<p>这些功能已被考虑实现了, 并且有些是实验性实现。但他们将会永远不被实现, 或者被删除。</p>
+
+<ul>
+ <li><strong>HTML imports</strong>, 因为我们想等着看看开发者如何使用ES6 模块 (虽然还没有实现; 查看 {{bug(568953)}}). imports是一个早期未完成实现,并且将会被删除从Firefox中。</li>
+</ul>
+
+<h2 id="在Firefox中使用垫片">在Firefox中使用垫片</h2>
+
+<p>这有些注意事项在Firefox中使用垫片的时候:</p>
+
+<ul>
+ <li>当你激活原生Web容器支持在Firefox中通过设置 {{pref("dom.webcomponents.enabled")}} 偏好 为 <code>true</code> 在  <code>about:config 中</code>, 这个未完成的原生实现开始运作并且垫片可能会出现混淆; 这会有很大的可能性出现崩溃.</li>
+ <li>一个使用 <a href="https://github.com/webcomponents/webcomponentsjs">webcomponents.js</a> 垫片生成的Shadow DOM 并没有完全包裹样式, 所以这个 样式 可能会溢出。 要注意使用垫片构建的网址当运行在不支持原生Shadow DOM的环境之下时可能会出现差异.</li>
+ <li>这个Shadow DOM 垫片运行时非常缓慢的以为他重写了DOM元素的原型来挂在它的功能 。</li>
+ <li>如果你不需要使用 Shadow DOM, 使用 <a href="https://github.com/webcomponents/webcomponentsjs">webcomponents-lite.js</a> 版本的 webcomponents.js 垫片是一个名明智的选择; 这个版本不填补 Shadow DOM.</li>
+</ul>
+</article>
+</div>
diff --git a/files/zh-cn/web/web_components/using_custom_elements/index.html b/files/zh-cn/web/web_components/using_custom_elements/index.html
new file mode 100644
index 0000000000..2beef20c92
--- /dev/null
+++ b/files/zh-cn/web/web_components/using_custom_elements/index.html
@@ -0,0 +1,253 @@
+---
+title: 使用 custom elements
+slug: Web/Web_Components/Using_custom_elements
+translation_of: Web/Web_Components/Using_custom_elements
+---
+<div>{{DefaultAPISidebar("Web Components")}}</div>
+
+<p class="summary">Web Components 标准非常重要的一个特性是,它使开发者能够将HTML页面的功能封装为 custom elements(自定义标签),而往常,开发者不得不写一大堆冗长、深层嵌套的标签来实现同样的页面功能。这篇文章将会介绍如何使用HTML的custom elements。</p>
+
+<div class="note">
+<p><strong>注意:</strong>Firefox、Chrome和Opera默认就支持 custom elements。Safari目前只支持 autonomous custom elements(自主自定义标签),而 Edge也正在积极实现中。</p>
+</div>
+
+<h2 id="概述">概述</h2>
+
+<p>{{domxref("CustomElementRegistry")}} 接口的实例用来处理 web 文档中的 custom elements — 该对象允许你注册一个 custom element,返回已注册 custom elements 的信息,等等。</p>
+
+<p>{{domxref("CustomElementRegistry.define()")}} 方法用来注册一个 custom element,该方法接受以下参数:</p>
+
+<ul>
+ <li>表示所创建的元素名称的符合 {{domxref("DOMString")}} 标准的字符串。注意,custom element 的名称不能是单个单词,且其中<a href="https://html.spec.whatwg.org/#valid-custom-element-name">必须要有短横线</a>。</li>
+ <li>用于定义元素行为的 <a href="/en-US/docs/Web/JavaScript/Reference/Classes">类</a> 。</li>
+ <li><code>可选参数</code>,一个包含 <code>extends</code> 属性的配置对象,是可选参数。它指定了所创建的元素继承自哪个内置元素,可以继承任何内置元素。</li>
+</ul>
+
+<p>作为示例,我们可以像这样定义一个叫做 <a href="https://mdn.github.io/web-components-examples/word-count-web-component/">word-count</a> 的 custom element:</p>
+
+<pre class="brush: js notranslate">customElements.define('word-count', WordCount, { extends: 'p' });</pre>
+
+<p>这个元素叫做 <code>word-count</code>,它的类对象是 <code>WordCount</code>, 继承自 {{htmlelement("p")}} 元素.</p>
+
+<p>一个 custom element 的类对象可以通过 ES 2015 标准里的类语法生成。所以,<code>WordCount</code>可以写成下面这样:</p>
+
+<pre class="brush: js notranslate">class WordCount extends HTMLParagraphElement {
+ constructor() {
+ // 必须首先调用 super 方法
+ super();
+
+ // 元素的功能代码写在这里
+
+ ...
+ }
+}</pre>
+
+<p>上面只是一个简单的例子,我们能做的不只这些。在构造函数中,我们可以设定一些生命周期的回调函数,在特定的时间,这些回调函数将会被调用。例如,<code>connectedCallback</code>会在 custom element首次被插入到文档DOM节点上时被调用,而 <code>attributeChangedCallback</code>则会在 custom element增加、删除或者修改某个属性时被调用。</p>
+
+<p>你可以在 {{anch("使用生命周期回调函数")}}段落中了解更多相关信息。</p>
+
+<p>共有两种 custom elements:</p>
+
+<ul>
+ <li><strong>Autonomous custom elements </strong>是独立的元素,它不继承其他内建的HTML元素。你可以直接把它们写成HTML标签的形式,来在页面上使用。例如 <code>&lt;popup-info&gt;</code>,或者是<code>document.createElement("popup-info")</code>这样。</li>
+ <li><strong>Customized built-in elements</strong> 继承自基本的HTML元素。在创建时,你必须指定所需扩展的元素(正如上面例子所示),使用时,需要先写出基本的元素标签,并通过 {{htmlattrxref("is")}} 属性指定custom element的名称。例如<code>&lt;p is="word-count"&gt;</code>, 或者 <code>document.createElement("p", { is: "word-count" })</code>。</li>
+</ul>
+
+<h2 id="示例">示例</h2>
+
+<p>让我们来看几个简单示例,来了解如何创建 custom elements。</p>
+
+<h3 id="Autonomous_custom_elements">Autonomous custom elements</h3>
+
+<p>我们来看一下 <code><a href="https://github.com/mdn/web-components-examples/tree/master/popup-info-box-web-component">&lt;popup-info-box&gt;</a></code> (查看<a href="https://mdn.github.io/web-components-examples/popup-info-box-web-component/">在线示例</a>),一个关于 autonomous custom element的例子。它包含有一个图标和一段文字,并且图标显示在页面上。在这个图标获取焦点时,它会显示一个包含该段文字的信息框,用于展示更多的信息。</p>
+
+<p>为了实现这个功能,首先创建一个JavaScript文件,定义一个叫做<code>PopUpInfo</code>的类,它继承自{{domxref("HTMLElement")}}。Autonomous custom elements 总是继承自<code>HTMLElement</code>。</p>
+
+<pre class="brush: js notranslate">class PopUpInfo extends HTMLElement {
+ constructor() {
+ // 必须首先调用 super方法
+  super();
+
+  // 元素的功能代码写在这里
+
+ ...
+ }
+}</pre>
+
+<p>上述代码片段中,类的构造函数{{jsxref("Classes.constructor","constructor")}}总是先调用<code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/super">super()</a></code>来建立正确的原型链继承关系。</p>
+
+<p>在构造函数中,我们会定义元素实例所拥有的全部功能。作为示例,我们首先会将shadow root附加到custom element上,然后通过一系列DOM操作创建custom element的内部阴影DOM结构,再将其附加到 shadow root上,最后再将一些CSS附加到 shadow root的style节点上。</p>
+
+<pre class="brush: js notranslate">// 创建一个 shadow root
+var shadow = this.attachShadow({mode: 'open'});
+
+// 创建一个 spans
+var wrapper = document.createElement('span');
+wrapper.setAttribute('class','wrapper');
+var icon = document.createElement('span');
+icon.setAttribute('class','icon');
+icon.setAttribute('tabindex', 0);
+var info = document.createElement('span');
+info.setAttribute('class','info');
+
+// 获取text属性上的内容,并添加到一个span标签内
+var text = this.getAttribute('text');
+info.textContent = text;
+
+// 插入 icon
+var imgUrl;
+if(this.hasAttribute('img')) {
+ imgUrl = this.getAttribute('img');
+} else {
+ imgUrl = 'img/default.png';
+}
+var img = document.createElement('img');
+img.src = imgUrl;
+icon.appendChild(img);
+
+// 创建一些 CSS,并应用到 shadow dom上
+var style = document.createElement('style');
+
+style.textContent = '.wrapper {' +
+// 简洁起见,省略了具体的CSS
+
+// 将创建的元素附加到 shadow dom
+
+shadow.appendChild(style);
+shadow.appendChild(wrapper);
+wrapper.appendChild(icon);
+wrapper.appendChild(info);</pre>
+
+<p>最后,我们使用之前提到的<code>define()</code>方法将 custom element注册到<code>CustomElementRegistry</code>上,在方法的参数里,我们指定了元素的名称,以及定义了元素功能的类。</p>
+
+<pre class="brush: js notranslate">customElements.define('popup-info', PopUpInfo);</pre>
+
+<p>现在我们可以在页面上使用我们定义的custom element了,就像下面这样:</p>
+
+<pre class="brush: html notranslate">&lt;popup-info img="img/alt.png" text="Your card validation code (CVC)
+ is an extra security feature — it is the last 3 or 4 numbers on the
+ back of your card."&gt;</pre>
+
+<div class="note">
+<p><strong>注意</strong>: 上方代码不是最新,你可以在这里找到<a href="https://github.com/mdn/web-components-examples/blob/master/popup-info-box-web-component/main.js">完整的源码</a>。</p>
+</div>
+
+<div class="note">
+<p><strong>译者提示</strong>: 在Chrome版本76.0.3809.132(正式版本)(64 位)中测试发现,<code>customElements.define()</code>必须在js文件中调用,且引用此js文件时必须在<code>script</code>标签上添加<code>defer</code>属性,否则<code>this.getAttribute('属性名称')</code>无法获取到值。</p>
+</div>
+
+<h3 id="Customized_built-in_elements">Customized built-in elements</h3>
+
+<p>现在让我们来看一下另一个有关customized built in element(自定义内置元素)的示例— <a href="https://github.com/mdn/web-components-examples/tree/master/expanding-list-web-component">expanding-list</a> (<a href="https://mdn.github.io/web-components-examples/expanding-list-web-component/">查看在线示例</a>)。该示例将所有的无序列表转化为一个可收起/展开的菜单。</p>
+
+<p>首先,我们定义一个元素的类,这和之前一样:</p>
+
+<pre class="brush: js notranslate">class ExpandingList extends HTMLUListElement {
+ constructor() {
+ // 必须首先调用 super方法
+ super();
+
+ // 元素的功能代码写在这里
+
+ ...
+ }
+}</pre>
+
+<p>在这里,我们不会详细解释元素的功能细节,你可以在源码中了解它的工作方式。这里的真正不同点在于元素继承的是{{domxref("HTMLUListElement")}} 接口,而不是{{domxref("HTMLElement")}}。所以它拥有{{htmlelement("ul")}} 元素所有的特性,以及在此基础上我们定义的功能,这是与独立元素(standalone element)不同之处。这也是为什么我们称它为 customized built-in元素,而不是一个autonomous元素。</p>
+
+<p>接下来,和之前一样,我们使用<code>define()</code>方法注册一个元素,但不同的是,我们需要添加一个配置对象,用于指定我们需要继承的元素:</p>
+
+<pre class="brush: js notranslate">customElements.define('expanding-list', ExpandingList, { extends: "ul" });</pre>
+
+<p>在页面上使用 built-in element看起来也会有所不同:</p>
+
+<pre class="brush: html notranslate">&lt;ul is="expanding-list"&gt;
+
+ ...
+
+&lt;/ul&gt;</pre>
+
+<p>你可以正常使用<code>&lt;ul&gt;</code>标签,也可以通过<code>is</code>属性来指定一个custom element的名称。</p>
+
+<div class="note">
+<p><strong>注意</strong>: 同样的,你可以在这里找到完整的 <a href="https://github.com/mdn/web-components-examples/blob/master/expanding-list-web-component/main.js">JavaScript 源码</a>。</p>
+</div>
+
+<div class="note">
+<p><strong>译者注:在 </strong>chrome 66 版本上,该示例无法正确工作,相关问题:</p>
+
+<p><a href="https://stackoverflow.com/questions/39986046/how-to-create-new-instance-of-an-extended-class-of-custom-elements">How to create new instance of an extended class of custom elements</a></p>
+</div>
+
+<h2 id="使用生命周期回调函数">使用生命周期回调函数</h2>
+
+<p>在custom element的构造函数中,可以指定多个不同的回调函数,它们将会在元素的不同生命时期被调用:</p>
+
+<ul>
+ <li><code>connectedCallback</code>:当 custom element首次被插入文档DOM时,被调用。</li>
+ <li><code>disconnectedCallback</code>:当 custom element从文档DOM中删除时,被调用。</li>
+ <li><code>adoptedCallback</code>:当 custom element被移动到新的文档时,被调用。</li>
+ <li><code>attributeChangedCallback</code>: 当 custom element增加、删除、修改自身属性时,被调用。</li>
+</ul>
+
+<p>我们来看一下它们的一下用法示例。下面的代码出自<a href="https://github.com/mdn/web-components-examples/tree/master/life-cycle-callbacks">life-cycle-callbacks</a>示例(<a href="https://mdn.github.io/web-components-examples/life-cycle-callbacks/">查看在线示例</a>)。这个简单示例只是生成特定大小、颜色的方块。custom element看起来像下面这样:</p>
+
+<pre class="brush: html notranslate">&lt;custom-square l="100" c="red"&gt;&lt;/custom-square&gt;</pre>
+
+<p>这里,类的构造函数很简单 — 我们将 shadow DOM附加到元素上,然后将一个{{htmlelement("div")}}元素和{{htmlelement("style")}}元素附加到 shadow root上:</p>
+
+<pre class="brush: js notranslate">var shadow = this.attachShadow({mode: 'open'});
+
+var div = document.createElement('div');
+var style = document.createElement('style');
+shadow.appendChild(style);
+shadow.appendChild(div);</pre>
+
+<p>示例中的关键函数是 <code>updateStyle()</code>—它接受一个元素作为参数,然后获取该元素的shadow root,找到<code>&lt;style&gt;</code>元素,并添加{{cssxref("width")}},{{cssxref("height")}}以及{{cssxref("background-color")}}样式。</p>
+
+<pre class="brush: js notranslate">function updateStyle(elem) {
+ var shadow = elem.shadowRoot;
+ var childNodes = shadow.childNodes;
+ for(var i = 0; i &lt; childNodes.length; i++) {
+ if(childNodes[i].nodeName === 'STYLE') {
+ childNodes[i].textContent = 'div {' +
+ ' width: ' + elem.getAttribute('l') + 'px;' +
+ ' height: ' + elem.getAttribute('l') + 'px;' +
+ ' background-color: ' + elem.getAttribute('c');
+ }
+ }
+}</pre>
+
+<p>实际的更新操作是在生命周期的回调函数中处理的,我们在构造函数中设定类这些回调函数。当元素插入到DOM中时,<code>connectedCallback()</code>函数将会执行 — 在该函数中,我们执行<code>updateStyle()</code> 函数来确保方块按照定义来显示;</p>
+
+<pre class="brush: js notranslate">connectedCallback() {
+ console.log('Custom square element added to page.');
+ updateStyle(this);
+}</pre>
+
+<p><code>disconnectedCallback()</code>和<code>adoptedCallback()</code>回调函数只是简单地将消息发送到控制台,提示我们元素什么时候从DOM中移除、或者什么时候移动到不同的页面:</p>
+
+<pre class="brush: js notranslate">disconnectedCallback() {
+ console.log('Custom square element removed from page.');
+}
+
+adoptedCallback() {
+ console.log('Custom square element moved to new page.');
+}</pre>
+
+<p>每当元素的属性变化时,<code>attributeChangedCallback()</code>回调函数会执行。正如它的属性所示,我们可以查看属性的名称、旧值与新值,以此来对元素属性做单独的操作。在当前的示例中,我们只是再次执行了<code>updateStyle()</code>函数,以确保方块的样式在元素属性值变化后得以更新:</p>
+
+<pre class="brush: js notranslate">attributeChangedCallback(name, oldValue, newValue) {
+ console.log('Custom square element attributes changed.');
+ updateStyle(this);
+}</pre>
+
+<p><code><font face="Open Sans, arial, x-locale-body, sans-serif"><span style="background-color: #ffffff;">需要注意的是,如果需要在元素属性变化后,触发 </span></font>attributeChangedCallback()</code>回调函数,你必须监听这个属性。这可以通过定义<code>observedAttributes()</code> get函数来实现,<code>observedAttributes()</code>函数体内包含一个 return语句,返回一个数组,包含了需要监听的属性名称:</p>
+
+<pre class="brush: js notranslate">static get observedAttributes() {return ['w', 'l']; }</pre>
+
+<p>在我们的例子中,该段代码处于构造函数的上方。</p>
+
+<div class="note">
+<p><strong>注意</strong>: 在这里查看<a href="https://github.com/mdn/web-components-examples/blob/master/life-cycle-callbacks/main.js">完整的 JavaScript源码</a>。</p>
+</div>
diff --git a/files/zh-cn/web/web_components/using_shadow_dom/index.html b/files/zh-cn/web/web_components/using_shadow_dom/index.html
new file mode 100644
index 0000000000..1267f49508
--- /dev/null
+++ b/files/zh-cn/web/web_components/using_shadow_dom/index.html
@@ -0,0 +1,221 @@
+---
+title: 使用 shadow DOM
+slug: Web/Web_Components/Using_shadow_DOM
+tags:
+ - API
+ - DOM
+ - Web Components
+ - 指南
+translation_of: Web/Web_Components/Using_shadow_DOM
+---
+<div>{{DefaultAPISidebar("Web Components")}}</div>
+
+<p class="summary">Web components 的一个重要属性是封装——可以将标记结构、样式和行为隐藏起来,并与页面上的其他代码相隔离,保证不同的部分不会混在一起,可使代码更加干净、整洁。其中,Shadow DOM 接口是关键所在,它可以将一个隐藏的、独立的 DOM 附加到一个元素上。本篇文章将会介绍 Shadow DOM 的基础使用。</p>
+
+<div class="note">
+<p><strong>备注:</strong> Firefox(从版本 63 开始),Chrome,Opera 和 Safari 默认支持 Shadow DOM。基于 Chromium 的新 Edge 也支持 Shadow DOM;而旧 Edge 未能撑到支持此特性。</p>
+</div>
+
+<h2 id="概况">概况</h2>
+
+<p>本文章假设你对 <a href="/en-US/docs/Web/API/Document_Object_Model/Introduction">DOM(文档对象模型)</a>有一定的了解,它是由不同的元素节点、文本节点连接而成的一个树状结构,应用于标记文档中(例如  Web 文档中常见的 HTML 文档)。请看如下示例,一段 HTML 代码:</p>
+
+<pre class="brush: html">&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+ &lt;head&gt;
+ &lt;meta charset="utf-8"&gt;
+ &lt;title&gt;Simple DOM example&lt;/title&gt;
+ &lt;/head&gt;
+ &lt;body&gt;
+ &lt;section&gt;
+ &lt;img src="dinosaur.png" alt="A red Tyrannosaurus Rex: A two legged dinosaur standing upright like a human, with small arms, and a large head with lots of sharp teeth."&gt;
+ &lt;p&gt;Here we will add a link to the &lt;a href="https://www.mozilla.org/"&gt;Mozilla homepage&lt;/a&gt;&lt;/p&gt;
+ &lt;/section&gt;
+ &lt;/body&gt;
+&lt;/html&gt;</pre>
+
+<p>这个片段会生成如下的 DOM 结构:</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/14559/dom-screenshot.png" style="border-style: solid; border-width: 1px; display: block; margin: 0px auto;"></p>
+
+<p><em>Shadow</em> DOM 允许将隐藏的 DOM 树附加到常规的 DOM 树中——它以 shadow root 节点为起始根节点,在这个根节点的下方,可以是任意元素,和普通的 DOM 元素一样。</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/15788/shadow-dom.png" style="height: 543px; width: 1138px;"></p>
+
+<p>这里,有一些 Shadow DOM 特有的术语需要我们了解:</p>
+
+<ul>
+ <li>Shadow host:一个常规 DOM节点,Shadow DOM 会被附加到这个节点上。</li>
+ <li>Shadow tree:Shadow DOM内部的DOM树。</li>
+ <li>Shadow boundary:Shadow DOM结束的地方,也是常规 DOM开始的地方。</li>
+ <li>Shadow root: Shadow tree的根节点。</li>
+</ul>
+
+<p>你可以使用同样的方式来操作 Shadow DOM,就和操作常规 DOM 一样——例如添加子节点、设置属性,以及为节点添加自己的样式(例如通过 <code>element.style</code> 属性),或者为整个 Shadow DOM 添加样式(例如在 {{htmlelement("style")}} 元素内添加样式)。不同的是,Shadow DOM 内部的元素始终不会影响到它外部的元素(除了 {{CSSxRef(":focus-within")}}),这为封装提供了便利。</p>
+
+<p>注意,不管从哪个方面来看,Shadow DOM 都不是一个新事物——在过去的很长一段时间里,浏览器用它来封装一些元素的内部结构。以一个有着默认播放控制按钮的 {{htmlelement("video")}} 元素为例。你所能看到的只是一个 <code>&lt;video&gt;</code> 标签,实际上,在它的 Shadow DOM 中,包含来一系列的按钮和其他控制器。Shadow DOM 标准允许你为你自己的元素(custom element)维护一组 Shadow DOM。</p>
+
+<h2 id="基本用法">基本用法</h2>
+
+<p>可以使用 {{domxref("Element.attachShadow()")}} 方法来将一个 shadow root 附加到任何一个元素上。它接受一个配置对象作为参数,该对象有一个 <code>mode</code> 属性,值可以是 <code>open</code> 或者 <code>closed</code>:</p>
+
+<pre class="brush: js">let shadow = elementRef.attachShadow({mode: 'open'});
+let shadow = elementRef.attachShadow({mode: 'closed'});</pre>
+
+<p><code>open</code> 表示可以通过页面内的 JavaScript 方法来获取 Shadow DOM,例如使用 {{domxref("Element.shadowRoot")}} 属性:</p>
+
+<pre class="brush: js">let myShadowDom = myCustomElem.shadowRoot;</pre>
+
+<p>如果你将一个 Shadow root 附加到一个 Custom element 上,并且将 <code>mode</code> 设置为 <code>closed</code>,那么就不可以从外部获取 Shadow DOM 了——<code>myCustomElem.shadowRoot</code> 将会返回 <code>null</code>。浏览器中的某些内置元素就是如此,例如<code>&lt;video&gt;</code>,包含了不可访问的 Shadow DOM。</p>
+
+<div class="note">
+<p><strong>备注:</strong> 正如<a href="https://blog.revillweb.com/open-vs-closed-shadow-dom-9f3d7427d1af">这篇文章所阐述的</a>,处理 closed Shadow DOM 实际上很简单,往往也很值得这么做。</p>
+</div>
+
+<p>如果你想将一个 Shadow DOM 附加到 custom element 上,可以在 custom element 的构造函数中添加如下实现(目前,这是 shadow DOM 最实用的用法):</p>
+
+<pre class="brush: js">let shadow = this.attachShadow({mode: 'open'});</pre>
+
+<p>将 Shadow DOM 附加到一个元素之后,就可以使用 DOM APIs对它进行操作,就和处理常规 DOM 一样。</p>
+
+<pre class="brush: js">var para = document.createElement('p');
+shadow.appendChild(para);
+etc.</pre>
+
+<h2 id="编写简单示例">编写简单示例</h2>
+
+<p>现在,让我们着手实现一个示例——<code><a href="https://github.com/mdn/web-components-examples/tree/master/popup-info-box-web-component">&lt;popup-info-box&gt;</a></code>(也可以查看<a href="https://mdn.github.io/web-components-examples/popup-info-box-web-component/">在线示例</a>),来说明 Shadow DOM 在 custom element 中的实际运用。它包含一个图片 icon 和一段文字,并将 icon 嵌入页面之中。每当 icon 获取到焦点时,文字会在一个弹框中显示,以提供更加详细的信息。首先,在 JavaScript 文件中,我们需要定义一个叫做 <code>PopUpInfo</code> 的类,它继承自 <code>HTMLElement</code>:</p>
+
+<pre class="brush: js">class PopUpInfo extends HTMLElement {
+ constructor() {
+ // 必须首先调用 super方法
+ super();
+
+ // 元素的具体功能写在下面
+
+ ...
+ }
+}</pre>
+
+<p>在上面的类中,我们将会在它的构造函数中定义元素所有的功能。当类实例化后,所有的实例元素都会有相同功能。</p>
+
+<h3 id="创建_shadow_root">创建 shadow root</h3>
+
+<p>在构造函数中,我们首先将 Shadow root 附加到 custom element 上:</p>
+
+<pre class="brush: js">// 创建 shadow root
+var shadow = this.attachShadow({mode: 'open'});</pre>
+
+<h3 class="brush: js" id="创建_shadow_DOM_结构">创建 shadow DOM 结构</h3>
+
+<p class="brush: js">接下来,我们会使用相关 DOM 操作来创建元素的 Shadow DOM 结构:</p>
+
+<pre class="brush: js">// 创建 span
+var wrapper = document.createElement('span');
+wrapper.setAttribute('class','wrapper');
+var icon = document.createElement('span');
+icon.setAttribute('class','icon');
+icon.setAttribute('tabindex', 0);
+var info = document.createElement('span');
+info.setAttribute('class','info');
+
+// 获取属性的内容并将内容添加到 info 元素内
+var text = this.getAttribute('text');
+info.textContent = text;
+
+// 插入 icon
+var imgUrl;
+if(this.hasAttribute('img')) {
+ imgUrl = this.getAttribute('img');
+} else {
+ imgUrl = 'img/default.png';
+}
+var img = document.createElement('img');
+img.src = imgUrl;
+icon.appendChild(img);
+</pre>
+
+<h3 class="brush: js" id="为_shadow_DOM_添加样式">为 shadow DOM 添加样式</h3>
+
+<p class="brush: js">之后,我们将要创建 {{htmlelement("style")}} 元素,并加入一些 CSS 样式:</p>
+
+<pre class="brush: js line-numbers language-js">// 为 shadow DOM 添加一些 CSS 样式
+var style = document.createElement('style');
+
+style.textContent = `
+.wrapper {
+ position: relative;
+}
+
+.info {
+ font-size: 0.8rem;
+ width: 200px;
+ display: inline-block;
+ border: 1px solid black;
+ padding: 10px;
+ background: white;
+ border-radius: 10px;
+ opacity: 0;
+ transition: 0.6s all;
+ position: absolute;
+ bottom: 20px;
+ left: 10px;
+ z-index: 3;
+}
+
+img {
+ width: 1.2rem;
+}
+
+.icon:hover + .info, .icon:focus + .info {
+ opacity: 1;
+}`;</pre>
+
+<h3 id="将_Shadow_DOM_添加到_Shadow_root_上">将 Shadow DOM 添加到 Shadow root 上</h3>
+
+<p>最后,将所有创建的元素添加到 Shadow root 上:</p>
+
+<pre class="brush: js">// 将所创建的元素添加到 Shadow DOM 上
+shadow.appendChild(style);
+shadow.appendChild(wrapper);
+wrapper.appendChild(icon);
+wrapper.appendChild(info);</pre>
+
+<h3 id="使用我们的_custom_element">使用我们的 custom element</h3>
+
+<p>完成类的定义之后,使用元素也是一样简单,只需将 custom element 放在页面上,正如 <a href="/en-US/docs/Web/Web_Components/Using_custom_elements">Using custom elements</a> 中讲解的那样:</p>
+
+<pre class="brush: js">// 定义新的元素
+customElements.define('popup-info', PopUpInfo);</pre>
+
+<pre class="brush: html">&lt;popup-info img="img/alt.png" text="Your card validation code (CVC) is an extra security feature — it is the last 3 or 4 numbers on the back of your card."&gt;</pre>
+
+<div>
+<div id="tap-translate"></div>
+</div>
+
+<h3 id="使用外部引入的样式">使用外部引入的样式</h3>
+
+<p>在上面的示例中,我们使用行内{{htmlelement("style")}} 元素为Shadow DOM添加样式,但是完全可以通过{{htmlelement("link")}} 标签引用外部样式表来替代行内样式。</p>
+
+<p>例如,我们可以看下 <a href="https://mdn.github.io/web-components-examples/popup-info-box-external-stylesheet/">popup-info-box-external-stylesheet</a> 例子 (查看源代码 <a href="https://github.com/mdn/web-components-examples/blob/master/popup-info-box-external-stylesheet/main.js">source code</a>):</p>
+
+<pre class="brush: js">// 将外部引用的样式添加到 Shadow DOM 上
+const linkElem = document.createElement('link');
+linkElem.setAttribute('rel', 'stylesheet');
+linkElem.setAttribute('href', 'style.css');
+
+// 将所创建的元素添加到 Shadow DOM 上
+
+shadow.appendChild(linkElem);</pre>
+
+<p>请注意, 因为{{htmlelement("link")}} 元素不会打断 shadow root 的绘制, 因此在加载样式表时可能会出现未添加样式内容(FOUC),导致闪烁。</p>
+
+<p>许多现代浏览器都对从公共节点克隆的或具有相同文本的{{htmlelement("style")}} 标签实现了优化,以允许它们共享单个支持样式表,通过这种优化,外部和内部样式的性能表现比较接近。</p>
+
+<h2 id="参见">参见</h2>
+
+<ul>
+ <li><a href="/zh-CN/docs/Web/Web_Components/Using_custom_elements">使用 custom elements</a></li>
+ <li><a href="/zh-CN/docs/Web/Web_Components/Using_templates_and_slots">使用 templates 与 slots</a></li>
+</ul>
diff --git a/files/zh-cn/web/web_components/using_templates_and_slots/index.html b/files/zh-cn/web/web_components/using_templates_and_slots/index.html
new file mode 100644
index 0000000000..b0551dcae5
--- /dev/null
+++ b/files/zh-cn/web/web_components/using_templates_and_slots/index.html
@@ -0,0 +1,334 @@
+---
+title: 使用 templates and slots
+slug: Web/Web_Components/Using_templates_and_slots
+tags:
+ - HTML slot
+ - HTML template
+ - HTML5
+ - Web Components
+ - shadow dom
+translation_of: Web/Web_Components/Using_templates_and_slots
+---
+<div>{{DefaultAPISidebar("Web Components")}}</div>
+
+<p class="summary">这篇文章阐述了如何使用 {{htmlelement("template")}} 和 {{htmlelement("slot")}} 元素创建一个可以用来灵活填充 Web组件的 shadow DOM 的模板。</p>
+
+<h2 id="关于模板_Templates">关于模板 (Templates)</h2>
+
+<p>当您必须在网页上重复使用相同的标记结构时,使用某种模板而不是一遍又一遍地重复相同的结构是有意义的。以前这是可行的,但HTML {{htmlelement("template")}} 元素使它更容易实现(这在现代浏览器中得到了很好的支持)。 此元素及其内容不会在DOM中呈现,但仍可使用JavaScript去引用它。</p>
+
+<p>让我们看一个简单的示例:</p>
+
+<pre class="brush: html notranslate">&lt;template id="my-paragraph"&gt;
+ &lt;p&gt;My paragraph&lt;/p&gt;
+&lt;/template&gt;</pre>
+
+<p>上面的代码不会展示在你的页面中,直到你用 JavaScript 获取它的引用,然后添加到DOM中, 如下面的代码:</p>
+
+<pre class="brush: js notranslate">let template = document.getElementById('my-paragraph');
+let templateContent = template.content;
+document.body.appendChild(templateContent);</pre>
+
+<p>虽然是个简单的例子,但您已经可以开始了解它是多么的有用了。</p>
+
+<h2 id="在Web_Components中使用模板">在Web Components中使用模板</h2>
+
+<p>模板(Templates) 本身就是有用的,  而与 web 组件(web component) 一起使用效果更好。我们定义一个 web 组件使用模板作为阴影(shadow) DOM 的内容,叫它 <code>&lt;my-paragraph&gt;</code>:</p>
+
+<pre class="brush: js notranslate">customElements.define('my-paragraph',
+ class extends HTMLElement {
+ constructor() {
+ super();
+ let template = document.getElementById('my-paragraph');
+ let templateContent = template.content;
+
+ const shadowRoot = this.attachShadow({mode: 'open'})
+ .appendChild(templateContent.cloneNode(true));
+ }
+})</pre>
+
+<p>要注意的关键是我们使用{{domxref("Node.cloneNode()")}} 方法添加了模板的拷贝到阴影的根结点上。</p>
+
+<p>因为我们添加了模板的内容到 shadow DOM, 所以我们可以加入一些样式信息到模板的 {{htmlelement("style")}} 标签里,这些样式信息稍后会封装到自定义的元素中。如果只给它添加到一个标准的DOM中是不起作用的。</p>
+
+<p>比如:</p>
+
+<pre class="brush: html notranslate">&lt;template id="my-paragraph"&gt;
+ &lt;style&gt;
+ p {
+ color: white;
+ background-color: #666;
+ padding: 5px;
+ }
+ &lt;/style&gt;
+ &lt;p&gt;My paragraph&lt;/p&gt;
+&lt;/template&gt;</pre>
+
+<p>现在我们将它添加自己的 HTML 文档中试试看:</p>
+
+<pre class="brush: html notranslate">&lt;my-paragraph&gt;&lt;/my-paragraph&gt;
+</pre>
+
+<div class="note">
+<p><strong>Note</strong>: 模板在浏览器中的支持情况很好,  Firefox(版本63及以上),Chrome,Opera ,Edge(版本79及以上) 和 Safari 支持 Shadow DOM</p>
+</div>
+
+<h2 id="使用槽slots_添加灵活度">使用槽(slots) 添加灵活度</h2>
+
+<p>尽管到这一步已经挺好了,但是元素仍旧不是很灵活. 我们只能在里面放一点文本, 甚至没有普通的 p 标签管用!我们使用 {{htmlelement("slot")}} 让它能在单个实例中通过声明式的语法展示不同的文本。浏览器对这个功能的支持比{{htmlelement("template")}}少,在Chrome 53, Opera 40, Safari 10, 火狐 59 和 Edge 79中支持。</p>
+
+<p>插槽由其<code>name</code>属性标识,并且允许您在模板中定义占位符,当在标记中使用该元素时,该占位符可以填充所需的任何HTML标记片段。</p>
+
+<p>如果你想添加一个槽到我们的这个例子,我们会将模板的 p 标签改成下面这样:</p>
+
+<pre class="brush: html notranslate">&lt;p&gt;&lt;slot name="my-text"&gt;My default text&lt;/slot&gt;&lt;/p&gt;
+</pre>
+
+<p>如果在标记中包含元素时未定义相关的插槽内容,或者浏览器不支持slot属性,则<code>&lt;my-paragraph&gt;</code>仅包含后备内容"My default text"。(译者注:此处的意思是使用&lt;my-paragraph&gt;时内部不包裹任何内容时会显示slot 定义好的默认值。具体使用可参考下面)</p>
+
+<p>要定义插槽内容,我们在<code>&lt;my-paragraph&gt;</code>元素内包括一个HTML结构,该结构具有{{htmlattrxref("slot")}}属性,其值等于我们要填充的{{htmlelement("slot")}}的name属性的值。 和以前一样,它可以是您喜欢的任何东西,例如:</p>
+
+<pre class="brush: html notranslate">&lt;my-paragraph&gt;
+ &lt;span slot="my-text"&gt;Let's have some different text!&lt;/span&gt;
+&lt;/my-paragraph&gt;</pre>
+
+<p>或者</p>
+
+<pre class="brush: html notranslate">&lt;my-paragraph&gt;
+ &lt;ul slot="my-text"&gt;
+ &lt;li&gt;Let's have some different text!&lt;/li&gt;
+ &lt;li&gt;In a list!&lt;/li&gt;
+ &lt;/ul&gt;
+&lt;/my-paragraph&gt;</pre>
+
+<p>以上为例。</p>
+
+<div class="note">
+<p><strong>Note</strong>: 将能被插入到槽中的元素视为 {{domxref("Slotable")}}; 称已经插入到槽中的元素为 <em>slotted</em>.</p>
+</div>
+
+<p>这就我们普通的例子,你想更深入了解你可以 <a href="https://github.com/mdn/web-components-examples/tree/master/simple-template">在GitHub上查看</a> (也可以看 <a href="https://mdn.github.io/web-components-examples/simple-template/">在线运行</a>)。</p>
+
+<h2 id="更深入的例子">更深入的例子</h2>
+
+<p>为了更好的结束这篇文章,我们来个看一些不寻常的例子。</p>
+
+<p>下面的一组代码段展示了我们如何联合使用 <code>&lt;slot&gt;</code> 和 <code>&lt;template&gt;</code> 以及一些 JavaScript 去完成:</p>
+
+<ul>
+ <li>使用 <a href="/en-US/docs/Web/HTML/Element/slot#named-slot">命名的槽(named slots)</a> 在 <a href="/en-US/docs/Web/API/ShadowRoot">阴影(shadow root)</a> 创建一个 <strong><code>&lt;element-details&gt;</code></strong> 元素。</li>
+ <li>将 <strong><code>&lt;element-details&gt;</code></strong> 元素设计成在文档中使用时, 它将它的 <a href="/en-US/docs/Web/API/ShadowRoot">shadow root</a> 中的内容和该元素内部的内容糅合在一起 —也就是元素内容中的片断被填充到元素的 <a href="/en-US/docs/Web/API/ShadowRoot">阴影(shadow root)</a> 的 <a href="/en-US/docs/Web/HTML/Element/slot#named-slot">命名的槽(named slots)</a> 中。</li>
+</ul>
+
+<p>注意,技术上来讲没有<code>&lt;template&gt;</code> 使用 <code>&lt;slot&gt;</code> 也是可以的。例如,  <code>&lt;slot&gt;</code> 在一个常规的{{HTMLElement("div")}} 标签里,仍然有占位符的特性,就像在 shadow DOM 中一样,这样我们能避免需要先获取模板对象的 <code>content</code> 属性再使用它的麻烦。然而这个特性在向一个 {{HTMLElement("template")}} 元素中添加槽时更加实用, 因为你不会基于一个渲染的元素定义一个模式。</p>
+
+<p>另外,就算它还没有渲染,使用{{HTMLElement("template")}}时,作为模板的容器应该语义上应当干净。而且 {{HTMLElement("template")}}   可以直接挂一些对象,如  {{HTMLElement("td")}} ,当加到一个 {{HTMLElement("div")}} 中时会隐藏。</p>
+
+<div class="note">
+<p><strong>Note</strong>: 查看在完整的例子在 <a href="https://github.com/mdn/web-components-examples/tree/master/element-details">element-details</a> ( <a href="https://mdn.github.io/web-components-examples/element-details/">在线运行</a> ).</p>
+</div>
+
+<h3 id="使用槽slot_创建一个模板">使用槽(slot) 创建一个模板</h3>
+
+<p>首先,我们在{{HTMLElement("template")}} 使用  <code>&lt;slot&gt;</code> 标签创建一个"element-details-template"包含一些 <a href="/en-US/docs/Web/HTML/Element/slot#named-slot">命名的槽(named slot)</a>  的 <a href="/en-US/docs/Web/API/DocumentFragment">文档片段(document fragment)</a></p>
+
+<pre class="brush: html notranslate">&lt;template id="element-details-template"&gt;
+  &lt;style&gt;
+  details {font-family: "Open Sans Light",Helvetica,Arial}
+  .name {font-weight: bold; color: #217ac0; font-size: 120%}
+  h4 { margin: 10px 0 -8px 0; }
+  h4 span { background: #217ac0; padding: 2px 6px 2px 6px }
+  h4 span { border: 1px solid #cee9f9; border-radius: 4px }
+  h4 span { color: white }
+  .attributes { margin-left: 22px; font-size: 90% }
+  .attributes p { margin-left: 16px; font-style: italic }
+  &lt;/style&gt;
+  &lt;details&gt;
+    &lt;summary&gt;
+      &lt;span&gt;
+ &lt;code class="name"&gt;&amp;lt;&lt;slot name="element-name"&gt;NEED NAME&lt;/slot&gt;&amp;gt;&lt;/code&gt;
+        &lt;i class="desc"&gt;&lt;slot name="description"&gt;NEED DESCRIPTION&lt;/slot&gt;&lt;/i&gt;
+      &lt;/span&gt;
+    &lt;/summary&gt;
+    &lt;div class="attributes"&gt;
+      &lt;h4&gt;&lt;span&gt;Attributes&lt;/span&gt;&lt;/h4&gt;
+      &lt;slot name="attributes"&gt;&lt;p&gt;None&lt;/p&gt;&lt;/slot&gt;
+    &lt;/div&gt;
+  &lt;/details&gt;
+  &lt;hr&gt;
+&lt;/template&gt;
+</pre>
+
+<p>上面这个{{HTMLElement("template")}} 有几个特征:</p>
+
+<ul>
+ <li>{{HTMLElement("template")}} 标签有一个 {{HTMLElement("style")}} 标签,里面有一些  只能在当前{{HTMLElement("template")}} 的派生中生效的 CSS 样式</li>
+ <li>{{HTMLElement("template")}} 用 <code>&lt;slot&gt;</code> 和它的 {{htmlattrxref("name", "slot")}} 属性生成一个 <a href="/en-US/docs/Web/HTML/Element/slot#named-slot">命名的槽(named slots)</a>:
+ <ul>
+ <li><code>&lt;slot name="element-name"&gt;</code></li>
+ <li><code>&lt;slot name="description"&gt;</code></li>
+ <li><code>&lt;slot name="attributes"&gt;</code></li>
+ </ul>
+ </li>
+ <li>{{HTMLElement("template")}} 包裹 <a href="/en-US/docs/Web/HTML/Element/slot#named-slot">命名的槽(named slots)</a> 在 {{HTMLElement("details")}} 元素中。</li>
+</ul>
+
+<h3 id="从&lt;template>_中创建一个新的_&lt;element-details>_对象">从&lt;template&gt; 中创建一个新的 &lt;element-details&gt; 对象</h3>
+
+<p>接下来,我们定义一个新的 <strong><code>&lt;element-details&gt;</code></strong> 元素然后用 {{DOMXref("Element.attachShadow")}} 来将它附着到它的 <a href="/en-US/docs/Web/API/ShadowRoot">阴影(shadow) root</a>, 这个阴影上我们创建了 {{HTMLElement("template")}} 元素。这和我们上面使用的简单例子中的一样。</p>
+
+<pre class="brush: js notranslate">customElements.define('element-details',
+ class extends HTMLElement {
+  constructor() {
+    super();
+    var template = document
+ .getElementById('element-details-template')
+ .content;
+    const shadowRoot = this.attachShadow({mode: 'open'})
+      .appendChild(template.cloneNode(true));
+  }
+})
+</pre>
+
+<h3 id="结合命名的_slots_使用自定义元素_&lt;element-details>">结合命名的 slots 使用自定义元素 &lt;element-details&gt;</h3>
+
+<p>现在让我们正式在文档流中使用&lt;element-details&gt;标签:</p>
+
+<pre class="brush: html notranslate">&lt;element-details&gt;
+ &lt;span slot="element-name"&gt;slot&lt;/span&gt;
+ &lt;span slot="description"&gt;A placeholder inside a web
+ component that users can fill with their own markup,
+ with the effect of composing different DOM trees
+ together.&lt;/span&gt;
+ &lt;dl slot="attributes"&gt;
+ &lt;dt&gt;name&lt;/dt&gt;
+ &lt;dd&gt;The name of the slot.&lt;/dd&gt;
+ &lt;/dl&gt;
+&lt;/element-details&gt;
+
+&lt;element-details&gt;
+ &lt;span slot="element-name"&gt;template&lt;/span&gt;
+ &lt;span slot="description"&gt;A mechanism for holding client-
+ side content that is not to be rendered when a page is
+ loaded but may subsequently be instantiated during
+ runtime using JavaScript.&lt;/span&gt;
+&lt;/element-details&gt;
+</pre>
+
+<p>关于以上代码片段,请注意以下几点:</p>
+
+<ul>
+ <li>该代码片段有2个 <strong><code>&lt;element-details&gt;</code> </strong>标签,他们都使用了“slot”属性来引用名为<code>"element-name"</code>和<code>"description"</code>的槽,并把他们都放在根下。</li>
+ <li>只有第一个 <strong><code>&lt;element-details&gt;</code></strong> 元素 引用了名为 <code>"attributes"</code> 的槽,而第二个 <code><strong>&lt;element-details</strong>&gt;</code> 标签没有引用名为<code>"attributes"</code>的槽。</li>
+ <li>只有第一个 <strong><code>&lt;element-details&gt;</code> </strong>标签中的"dl"使用了名为 <code>"attributes"</code>的槽,他包含子元素:"dt"和"dd"元素。</li>
+</ul>
+
+<h3 id="添加一些最终的样式">添加一些最终的样式</h3>
+
+<p>在完成之前,我们在文档中给"dl"和"dt"以及"dd"标签增加一些CSS样式。</p>
+
+<pre class="brush: css notranslate">  dl { margin-left: 6px; }
+  dt { font-weight: bold; color: #217ac0; font-size: 110% }
+  dt { font-family: Consolas, "Liberation Mono", Courier }
+  dd { margin-left: 16px }
+</pre>
+
+<div class="hidden">
+<pre class="brush: css notranslate">body { margin-top: 47px }</pre>
+</div>
+
+<h3 id="结果">结果</h3>
+
+<p>最后,让我们所有的代码片段结合在一起,看看渲染的结果是什么样的。</p>
+
+<p>{{ EmbedLiveSample('full_example', '300','400','https://mdn.mozillademos.org/files/14553/element-details.png','') }}</p>
+
+<p>关于结果请注意以下几点:</p>
+
+<ul>
+ <li>即使 <strong><code>&lt;element-details&gt;</code> </strong>标签并没有直接使用<code>"details"</code>标签元素,但是在渲染的时候使用了<code>"details"</code>标签,是因为shadow root使得他们被填充。</li>
+ <li>在渲染出来的<code>"details"</code>标签,<code><strong>&lt;element-details&gt;</strong></code> 标签从根开始填充了相应的命名的槽。换言之,<strong><code>&lt;element-details&gt;</code></strong> 的DOM树和shadow root的内容结合在了一起。</li>
+ <li>对于这两个 <code><strong>&lt;element-details&gt;</strong></code> 标签,属性标题会自动的从shadow root中添加到名为<code>"attribute"</code>的插槽的前面。</li>
+ <li>因为第一个 <code><strong>&lt;element-details&gt;</strong></code> 标签的<code>"dl"</code>元素就明确的引用了名为<code>"attributes"</code>的插槽,所以该<code>"dl"</code>元素的内容将会替换该标签中名为<code>"attributes"</code>的插槽。</li>
+ <li>因为第二个 <code><strong>&lt;element-details&gt;</strong></code>标签没有引用名为<code>"attributes"</code> 的槽,所以标签内名为<code>"attributes"的</code>插槽的内容将会使用模板中默认的内容。</li>
+</ul>
+
+<div class="hidden">
+<h5 id="full_example">full example</h5>
+
+<pre class="brush: html notranslate">&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+ &lt;head&gt;
+ &lt;title&gt;slot example&lt;/title&gt;
+ &lt;style&gt;
+
+ dl { margin-left: 6px; }
+ dt { font-weight: bold; color: #217ac0; font-size: 110% }
+ dt { font-family: Consolas, "Liberation Mono", Courier }
+ dd { margin-left: 16px }
+
+ &lt;/style&gt;
+ &lt;/head&gt;
+ &lt;body&gt;
+ &lt;template id="element-details-template"&gt;
+ &lt;style&gt;
+ details {font-family: "Open Sans Light",Helvetica,Arial}
+ .name {font-weight: bold; color: #217ac0; font-size: 120%}
+ h4 { margin: 10px 0 -8px 0; }
+ h4 span { background: #217ac0; padding: 2px 6px 2px 6px }
+ h4 span { border: 1px solid #cee9f9; border-radius: 4px }
+ h4 span { color: white }
+ .attributes { margin-left: 22px; font-size: 90% }
+ .attributes p { margin-left: 16px; font-style: italic }
+ &lt;/style&gt;
+ &lt;details&gt;
+ &lt;summary&gt;
+ &lt;span&gt;
+ &lt;code class="name"&gt;&amp;lt;&lt;slot name="element-name"&gt;NEED NAME&lt;/slot&gt;&amp;gt;&lt;/code&gt;
+ &lt;i class="desc"&gt;&lt;slot name="description"&gt;NEED DESCRIPTION&lt;/slot&gt;&lt;/i&gt;
+ &lt;/span&gt;
+ &lt;/summary&gt;
+ &lt;div class="attributes"&gt;
+ &lt;h4&gt;&lt;span&gt;Attributes&lt;/span&gt;&lt;/h4&gt;
+ &lt;slot name="attributes"&gt;&lt;p&gt;None&lt;/p&gt;&lt;/slot&gt;
+ &lt;/div&gt;
+ &lt;/details&gt;
+ &lt;hr&gt;
+ &lt;/template&gt;
+
+ &lt;element-details&gt;
+ &lt;span slot="element-name"&gt;slot&lt;/span&gt;
+ &lt;span slot="description"&gt;A placeholder inside a web
+ component that users can fill with their own markup,
+ with the effect of composing different DOM trees
+ together.&lt;/span&gt;
+ &lt;dl slot="attributes"&gt;
+ &lt;dt&gt;name&lt;/dt&gt;
+ &lt;dd&gt;The name of the slot.&lt;/dd&gt;
+ &lt;/dl&gt;
+ &lt;/element-details&gt;
+
+ &lt;element-details&gt;
+ &lt;span slot="element-name"&gt;template&lt;/span&gt;
+ &lt;span slot="description"&gt;A mechanism for holding client-
+ side content that is not to be rendered when a page is
+ loaded but may subsequently be instantiated during
+ runtime using JavaScript.&lt;/span&gt;
+ &lt;/element-details&gt;
+
+ &lt;script&gt;
+ customElements.define('element-details',
+ class extends HTMLElement {
+ constructor() {
+ super();
+ const template = document
+ .getElementById('element-details-template')
+ .content;
+ const shadowRoot = this.attachShadow({mode: 'open'})
+ .appendChild(template.cloneNode(true));
+ }
+ })
+ &lt;/script&gt;
+ &lt;/body&gt;
+&lt;/html&gt;</pre>
+</div>
diff --git a/files/zh-cn/web/web_components/影子_dom/index.html b/files/zh-cn/web/web_components/影子_dom/index.html
new file mode 100644
index 0000000000..22f4c4c75d
--- /dev/null
+++ b/files/zh-cn/web/web_components/影子_dom/index.html
@@ -0,0 +1,90 @@
+---
+title: 影子DOM(Shadow DOM)
+slug: Web/Web_Components/影子_DOM
+tags:
+ - DocumentFragment
+ - React
+ - Virtual DOM
+ - Web Components
+ - shadow dom
+translation_of: Web/Web_Components/Using_shadow_DOM
+---
+<p>{{ draft }}</p>
+
+<p><strong>Shadow DOM </strong>为<a href="/zh-CN/docs/Web/Web_Components">Web组件</a>中的 DOM和 CSS提供了封装。Shadow DOM 使得这些东西与主文档的DOM保持分离。你也可以在一个Web组件外部使用 Shadow DOM本身。</p>
+
+<p>为什么要把一些代码和网页上其他的代码分离?原因之一是,大型站点若CSS没有良好的组织,导航的样式可能就『泄露』到本不应该去的地方,如主要内容区域,反之亦然。随着站点、应用的拓展,这样的事难以避免。</p>
+
+<h2 id="Shadow_DOM基础">Shadow DOM基础</h2>
+
+<p>Shadow DOM 必须附加在一个元素上,可以是HTML文件中的一个元素,也可以是脚本中创建的元素;可以是原生的元素,如&lt;div&gt;、&lt;p&gt;;也可以是<a href="/en-US/docs/Web/Web_Components/Custom_Elements">自定义元素</a>如 <code>&lt;my-element&gt;。</code> 如下例所示,使用 {{domxref("Element.<code>attachShadow</code>()")}} 来附加影子DOM:</p>
+
+<pre class="brush: html">&lt;html&gt;
+  &lt;head&gt;&lt;/head&gt;
+  &lt;body&gt;
+    &lt;p id="hostElement"&gt;&lt;/p&gt;
+    &lt;script&gt;
+      // create shadow DOM on the &lt;p&gt; element above
+      var shadow = document.querySelector('#hostElement').<code>attachShadow({mode: 'open'})</code>;
+    &lt;/script&gt;
+  &lt;/body&gt;
+&lt;/html&gt;</pre>
+
+<p>上例中给一个没有内容的 &lt;p&gt; 元素添加了影子DOM。显示没有变化。接下来,同样在上例中加入下列代码,可以在影子DOM中插入文字,并将在浏览器中显示:</p>
+
+<pre class="brush: js" style="font-size: 14px;">shadow.innerHTML = '&lt;p&gt;Here is some new text&lt;/p&gt;';</pre>
+
+<h3 id="Shadow_DOM_样式化">Shadow DOM 样式化</h3>
+
+<p><code>&lt;style&gt;</code> 元素可用来给影子DOM添加样式。 同样是上例,下列代码会将影子DOM中的文字变为红色:</p>
+
+<pre class="brush: html">&lt;script&gt;
+  // 创建 shadow DOM
+  var shadow = document.querySelector('#hostElement').<code>attachShadow({mode: 'open'})</code>;
+  // 给 shadow DOM 添加文字
+  shadow.innerHTML = '&lt;p&gt;Here is some new text&lt;/p&gt;';
+  // 添加CSS,将文字变红
+  shadow.innerHTML += '&lt;style&gt;p { color: red; }&lt;/style&gt;';
+&lt;/script&gt;
+</pre>
+
+<h3 id="Shadow_DOM_的组成部分:">Shadow DOM 的组成部分:</h3>
+
+<p>影子DOM由下列部分组成:</p>
+
+<ul>
+ <li>{{domxref("Element.attachShadow()")}}</li>
+ <li>{{domxref("Element.getDestinationInsertionPoints()")}}</li>
+ <li>{{domxref("Element.shadowRoot")}}</li>
+ <li><a href="/en-US/docs/Web/HTML/Element/Content">&lt;content&gt; 元素</a></li>
+ <li><a href="/en-US/docs/Web/HTML/Element/Shadow">&lt;shadow&gt; 元素</a></li>
+ <li>这些元素已从规范中移除: &lt;content&gt;, &lt;element&gt; 和&lt;decorator&gt;</li>
+ <li>相关API接口:{{domxref("ShadowRoot")}}, {{domxref("HTMLTemplateElement")}} and {{domxref("HTMLSlotElement")}}</li>
+ <li>CSS 选择器:
+ <ul>
+ <li>伪类:{{cssxref(":host")}}, {{cssxref(":host()")}}, {{cssxref(":host-context()")}}</li>
+ <li>伪元素:{{cssxref("::shadow")}} and {{cssxref("::content")}}</li>
+ <li>组合器:<code>&gt;&gt;&gt;</code> (formerly <code>/deep/</code>)*</li>
+ </ul>
+ </li>
+</ul>
+
+<p>* 将来<a href="https://bugs.chromium.org/p/chromium/issues/detail?id=489954">子组合器有可能被弃用</a></p>
+
+<h2 id="Interfaces">Interfaces</h2>
+
+<p>{{domxref("ShadowRoot")}}</p>
+
+<p>DOM子树的根节点,和文档的主要DOM树分开渲染。</p>
+
+<p>{{domxref("HTMLTemplateElement")}}</p>
+
+<p>允许访问HTML元素的内容。</p>
+
+<p>{{domxref("HTMLSlotElement")}}</p>
+
+<p>定义一个槽的位置。</p>
+
+<p>{{domxref("DocumentOrShadowRoot")}}</p>
+
+<p>提供在文档和 Shadow 树之间共享的API。</p>