使用ShadowDOM创建Web组件

   2015-06-26 0
核心提示:Web Components(组件)标准是一系列最新推出的标准,它可以被用来创建可被复用的Web部件,当页面中所使用的Web部件被更新为新版本时不必修改 页面中其他任何代码。这里所说的部件,是一种可实现与用户之间的交互的可视化组件,开发者可以使用HTML代码与JavaScript脚本代码来开发这些 部件。Web Componnts标准定义如何开发这些部件。

本文概述

Web Components(组件)标准是一系列最新推出的标准,它可以被用来创建可被复用的Web部件,当页面中所使用的Web部件被更新为新版本时不必修改 页面中其他任何代码。这里所说的部件,是一种可实现与用户之间的交互的可视化组件,开发者可以使用HTML代码与JavaScript脚本代码来开发这些 部件。Web Componnts标准定义如何开发这些部件。

目前为止,由于一些基本问题,导致使用HTML代码与JavaScript脚本代码开发出来的部件很难被应用在页面中,这些问题包括:一个部 件内的DOM树并没有被封装,这意味着你的样式表中的样式可能被意外地被应用到部件中,你的JavaScript脚本代码可能会修改部件中的某个部分,你 定义的ID可能会与部件内部所使用的ID相同等等。

最糟糕的是,由于部件没有被封装,如果你更新了部件,更改了其中的内部细节,你的页面上的样式表及JavaScript脚本代码可能会导致意想不到的结果。

一个Web组件通常由四个部分组成:模板、Shadow DOM、自定义元素与打包,其中Shadow DOM解决了组件在页面中的封装问题。可以结合使用这四个部分,也可以单独使用其中的一两个部分。本文介绍如何使用Shadom DOM。目前为止只有Chrome 25浏览器支持Shadow DOM,且使用时必须书写webkit前缀。

简单示例程序

通过Shadow DOM的使用,元素可以拥有一种新的被称为shadow root的节点,这时该元素被称为shadow容器。浏览器中不会渲染shadow容器中原有内容,而是渲染shadow root节点中的内容。

例如,你可以将HTML页面书写为如下所示:

  1. <button>click me</button> 
  2. <script> 
  3. var host = document.querySelector('button'); 
  4. var root = host.webkitCreateShadowRoot(); 
  5. root.textContent = '点击我'
  6. </script> 

通过这段代码,按钮中原有文字“click me”将被替换为“点击我”。请注意,在JavaScript脚本代码中,按钮的textContent属性值仍然为“click me”,而不是“点击我”,因为在DOM树中shadow root节点是被忽视的。

一个容易被违反的规则是:你不应该将页面内容安排在shadow root节点中。页面内容必须是屏幕阅读器、搜索引擎、浏览器扩展所能访问到的内容。Shadow DOM从语义上来说是没有任何意义的,它只被用来动态创建一个Web组件,而该Web组件中的任何内容也能被显示在页面中。当然,我们不是被强制使用该方 法来创建Web组件。

分离内容与展示

接下来,我们来看如何使用Shadow DOM将内容与展示进行分离。我们具有如下图所示的一个Web组件。

使用ShadowDOM创建Web组件

其样式代码与HTML页面代码如下所示(不使用Shadow DOM):

  1. <style> 
  2. .outer { 
  3.     border: 2px solid brown; 
  4.     border-radius: 1em; 
  5.     background: red; 
  6.     font-size: 20pt; 
  7.     width: 12em; 
  8.     height: 7em; 
  9.     text-align: center; 
  10. .boilerplate { 
  11.     color: white; 
  12.     font-family: sans-serif; 
  13.     padding: 0.5em; 
  14. .name { 
  15.     color: black; 
  16.     background: white; 
  17.     font-family: "宋体"; 
  18.     font-size: 30pt; 
  19.     padding-top: 0.2em; 
  20. </style> 
  21. <div class="outer"> 
  22.     <div class="boilerplate"> 
  23.         你好,欢迎来到 
  24.     </div> 
  25.     <div class="name"> 
  26.         HTML 5在线 
  27.     </div> 
  28. </div> 

因为这个Web组件没有被封装,其样式代码与HTML代码是被直接书写在样式代码与页面HTML代码中的,所以只要有人在其他地方不小心修改或重定义了该Web组件所使用的样式类代码,该组件就被破坏了。我们需要避免这种情况。

第一步:隐藏展示细节

在这段代码中,我们可能已经注意到:其中有一个样式类名为name的div元素,其中显示“HTML 5在线”文字。首先,我们将该元素的HTML代码修改为如下所示:

  1. <div id="nameComponent">HTML 5在线</div> 

然后,我们将所有该Web部件用样式代码与HTML代码书写到一个id为nameComponentTemplate的template元素中:

  1. <div id="nameComponent">HTML 5在线</div> 
  2. <template id="nameComponentTemplate"> 
  3. <style> 
  4. .outer { 
  5.     border: 2px solid brown; 
  6.     border-radius: 1em; 
  7.     background: red; 
  8.     font-size: 20pt; 
  9.     width: 12em; 
  10.     height: 7em; 
  11.     text-align: center; 
  12. .boilerplate { 
  13.     color: white; 
  14.     font-family: sans-serif; 
  15.     padding: 0.5em; 
  16. .name { 
  17.     color: black; 
  18.     background: white; 
  19.     font-family: "宋体"; 
  20.     font-size: 30pt; 
  21.     padding-top: 0.2em; 
  22. </style> 
  23. <div class="outer"> 
  24.     <div class="boilerplate"> 
  25.         你好,欢迎来到 
  26.     </div> 
  27.     <div class="name"> 
  28.         HTML 5在线 
  29.     </div> 
  30. </div> 
  31. </template> 

现在,该Web组件在页面上不可见,因为我们将它移到了一个template元素中,我们可以在JavaScript脚本代码中访问该Web组件。现在,我们将它放入nameComponent元素的shadow root节点中,代码如下所示:

  1. <script> 
  2. var shadow = document.querySelector('#nameComponent').webkitCreateShadowRoot(); 
  3. var template = document.querySelector('#nameComponentTemplate'); 
  4. shadow.appendChild(template.content); 
  5. template.remove(); 
  6. </script> 

现在,该组件将仍然被显示在页面上。如果你用鼠标右击nameComponent元素并查看元素内容,你将只能看见如下所示的内容:

  1. <div id="nameComponent">HTML 5在线</div> 

由此证明,通过Shadow DOM的使用,我们可以隐藏Web组件的展示细节,因为该细节被封装在元素的shadow root节点中。

第二步:分离内容与展示

现在我们的Web组件的展示细节已经被隐藏起来了,但Web组件中的内容并没有被独立出来,因为尽管组件内容(“HTML 5在线”)被显示在了页面上,但是该内容是通过被复制在元素的shadow root节点中的方法显示出来的。如果我们要修改组件内容,我们要再一次将其复制到元素的shadow root节点中。

在HTML 中,元素是可组合的,例如你可以在一个table元素中放入一个按钮。此处我们要实现的就是这种组合:在背景色为红色的容器元素中放入一个“HTML 5在线”文字。

你可以通过一个新的被称为content的元素来自定义你的Web组件中的部分内容。该元素在Web组件中创建一个注入点,在JavaScript脚本代码中可以向该注入点中动态注入内容。

接下来,我们首先修改template元素中的代码如下所示:

  1. <template id="nameComponentTemplate"> 
  2. <style> 
  3. ... 
  4. </style> 
  5. <div class="outer"> 
  6.     <div class="boilerplate"> 
  7.         你好,欢迎来到 
  8.     </div> 
  9.     <div class="name"> 
  10.         <content></content> 
  11.     </div> 
  12. </div> 
  13. </template> 

现在我们的Web部件仍将被渲染在页面上,但是原有“HTML 5在线”文字内容将被动态注入在content元素中。

如果你需要修改该文字内容,你可以使用如下所示的代码:

  1. document.querySelector('#nameComponent').textContent = '陆凌牛'

现在我们已经实现了内容与展示的分离。内容被显示在页面中,而在Web组件内部实现内容的展示。

将内容与展示分离的好处

将内容与展示分离的好处在于:我们可以很轻松地实现对组件内容的控制。例如在上述示例中,如果需要修改“HTML 5在线”文字,我们只需修改shadow root节点中的内容(即textContent属性值)即可,不需书写其他任何代码。

如果要修改组件中的其他任何内容或样式,我们也只需要修改template元素中的样式代码或HTML代码即可:

  1. <template id="nameComponentTemplate"> 
  2. <style> 
  3. .outer { 
  4.     border: 2px solid brown; 
  5.     border-radius: 1em; 
  6.     background: red; 
  7.     font-size: 20pt; 
  8.     width: 12em; 
  9.     height: 7em; 
  10.     text-align: center; 
  11. .boilerplate { 
  12.     color: white; 
  13.     font-family: sans-serif; 
  14.     padding: 0.5em; 
  15.  .littleFontSize{     font-size: 15pt; }   
  16. .name { 
  17.     color: black; 
  18.     background: white; 
  19.     font-family: "宋体"; 
  20.     font-size: 30pt; 
  21.     padding-top: 0.2em; 
  22. </style> 
  23. <div class="outer"> 
  24.     <div class="boilerplate"> 
  25.         你好,欢迎来到 
  26.     </div> 
  27.     <div class="name"> 
  28.         <content></content> 
  29.     </div> 
  30.          <div class="boilerplate littleFontSize"> 国内首家在桌面浏览器中正式应用HTML 5技术的技术网站。     </div>      
  31. </div> 
  32. </template> 

事实上,这个好处可以说是对目前Web技术的一个重大改善,因为你只需关注组件内部的实现代码,而不需关注外部如何使用这个组件。 例如在上述示例中,我们可以在为中文页面提供的组件中书写“你好,欢迎来到”文字,而在为英文页面提供的组件中书写“Hello,welcome to”文字。

实现高级注入

在上面这个示例代码中,可以动态向content元素中注入任何内容。事实上,我们可以使用多个content元素,并且通过select属性定义每个content元素中所显示内容的样式。

例如,你可以定义一个Web组件,其中的内容如下所示:

  1. <div class='first'>示例文字1</div> 
  2. <div class='second'>示例文字2</div> 
  3. <div class='three'>示例文字3</div> 

我们可以定义一个使用CSS样式选择器的shadow root节点,其代码如下所示:

  1. <template id="nameComponentTemplate">                 
  2.     <div style="background: purple; padding: 1em;"> 
  3.         <div style="color: red;"> 
  4.             <content select=".first"></content> 
  5.         </div> 
  6.         <div style="color: yellow;"> 
  7.             <content select=".second"></content> 
  8.         </div> 
  9.         <div style="color: blue;"> 
  10.             <content select=".three"></content> 
  11.         </div> 
  12.     </div> 
  13. </template> 

在这段代码中,每一个div元素都与<content select="div">元素相匹配,<div class='first'>元素同时与<content select="first">元素相匹配,<div class='secong'>元素同时与<content select="second">元素相匹配,,<div class='three'>元素同时与<content select="three">元素相匹配。从运行结果中我们可以看出,<div class='three'>元素的背景色为紫色,文字为蓝色,这是因为我们在组件内部定义所有div元素的背景色为紫色,且内容为< content select="first">的div元素的文字颜色为蓝色的缘故。

本文小结

本文对Shadow DOM做一基础介绍。你可以通过Shadow DOM实现更为复杂的处理。例如,你可以在一个shadow容器中实现多个shadow root节点,可以在shadow root节点中放置shadow容器(即在Web组件中嵌套使用Web组件)。在Web组件标准中,包含除Shadow DOM之外的更多内容。例如通过Custom Element(定制元素)的使用,你可以使用声明的方式,而不是使用书写脚本代码的方式来创建组件。

【编辑推荐】

【责
 
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • Handlebars模板引擎介绍和开发指南
    Handlebars是一个Javascript模板引擎,能让你轻松高效的编写语义化模板,它是Mustache模板引擎的一个扩展,Handlebars和Mustache都是弱逻辑的模板引擎,能将Web前端的视图和代码分离,降低两者之间耦合。
    06-26
  • KendoUI2014移动调查报告:HTML5vs原生之辩
    KendoUI2014移动调查报告:HTML5vs原生之辩
    Telerik Kendo UI一直比较关心移动开发领域的使用情况,在最新的2014 HTML5全球开发者调查中,Kendo UI面向3500+个开发者,从普通程序员到CIO/CTO,从大型企业到小型企业,对他们的移动开发偏好展开了调查。
    06-26
  • WebComponents-面向未来的组件标准
    WebComponents-面向未来的组件标准
    对于前端开发者而言,W3C组织制定的HTML标准以及浏览器厂商的实现都是“鱼”而 不是“渔”,开发者在需求无法满足的情况下通过现有技术创造了各种组件,虽然短期满足了需求但是由于严重缺乏标准,导致同一个组件有成千上万的相似实现但 它们却无法相互重用,这很大程度上制约了组件化的最大价值-重用,Web Components则在组件标准化方面向前迈了一大步。
    06-26
  • AppCan:HybridApp技术已经成熟
    AppCan:HybridApp技术已经成熟
    在移动开发技术里,Native App和Web App之争一直没有停息,而介于Native和Web之间的Hybrid混合App异军突起,以其接近Web App开发简单、跨平台能力,以及接近Native App功能和性能表现逐渐为开发者们所接受,那么,现在Hybrid App发展到了什么程度呢?正益无线技术支持总监邱革节在接受51CTO记者采访时表示,Hybrid App技术已经成熟。
    06-26
  • 什么是ShadowDom?
    什么是ShadowDom?
    如果我需要把每个自定义的按钮都放到iframe里,你是什么感觉,会不会疯掉?所以,我们需要一些更好的东西。事实上,大部分的浏览器已经变相地提供了一种强大技术去隐藏一些实现细节。这个技术就是所谓的“shadow DOM”。
    06-26
  • GooglePolymer以及WebUI框架的未来
    开发者Axel Rauschmayer在自己的博客上详解了Google Polymer的设计理念与组成架构,深得Polymer开发者的认同。他认为Polymer这样高互操作性的设计才应该是Web开发的未来。
    06-26
  • WebComponents实例:移动UI组件库GMU介绍
    GMU(Global Mobile UI)是百度前端通用组开发的移动端组件库,具有代码体积小、简单、易用等特点,组件内部处理了很多移动端的bug,覆盖机型广,能大大减少开发交互型组件的工作量,非常适合移动端网站项目。
    06-26
  • 移动应用新趋势:离线WebApp
    移动业界已经最终放弃了不分时间、不分地点为用户提供互联网连接服务的幻想。我们也看到了一系列新型产品与服务,它们的兴起标志着我们将以更为灵活的方式在无法接入网络时继续享受功能与便利。
    06-26
  • 2014年Web开发的7个转变方向
    2014年Web开发的7个转变方向
    很多读者喜欢预测网页设计趋势,让自己能够在网页设计、甚至网络发展中保持先机。找准每一年的发展趋势很重要。那么,2014年会有怎样的发展?我们一起来分析。
    06-26
  • 移动WebApp开发必备知识
    移动WebApp开发必备知识
    移动设备的用户越来越多,每天android手机的激活量都已经超过130万台,所以我们面向移动终端的WebAPP也开始跟进了。本文主要介绍webapp的开发与调试的相关知识和经验,以及给出几种可选的解决方案。
    06-26