windows标准组件调用_实施标准组件

windows标准组件调用

在这个由三部分组成的系列的前两篇文章中,您学习了如何实现HTML5临时滑块组件。 该组件提供了许多复杂的功能。 例如,当用户单击滑块的轨道时,它使用CSS3过渡平滑地滑动滑块的旋钮。 但是(从系列的第一篇文章中可以看到),从开发人员的角度来看,在应用程序中使用内置HTML元素并不那么简单。

要使用临时滑块,您必须:

  1. 在您HTML中添加一个空的DIV
  2. 创建一个新的COREHTML5.Slider
  3. 将在步骤2中创建的滑块追加到在步骤1中创建的空DIV中。
  4. 实现事件处理程序以将控件连接到滑块。

除了难以使用之外,临时滑块还容易受到滥用,无论是否故意。 任何人都可以访问该滑块的元素,因为-与当今几乎所有其他所有JavaScript即席组件一样-滑块将它们直接添加到DOM树中。

减少前面的步骤以简单地向HTML添加一个Slider标签将是理想的。 这就是您将通过使用以下API将即席滑块变成标准HTML5组件来完成的操作:

  • Shadow DOM :Shadow DOM API使您可以将通过常规方式无法访问的元素添加到DOM树中,例如document.getElementById() 。 Shadow DOM中的元素在阴影中潜伏; 它们对于DOM树的其余部分实际上是不可见的,并且默认情况下,它们不受周围文档中CSS的影响。
  • 模板 :HTML5模板是惰性文档片段。 当您需要显示该片段时,您可以标记 ( 创建 )模板,从而使该片段在DOM树中生效。 模板使您可以封装可以标记和定制HTML,JavaScript和CSS。
  • 自定义元素 :自定义元素是组件的标签。 它们与内置HTML标记没有区别,但自定义组件的标记必须包含连字符(例如<custom-tag> )。
  • HTML导入 :HTML导入使您可以从另一个导入一个HTML文件,这使您可以在其自己的文件中实现自定义组件。

这些API仍在开发中。 在撰写本文时,还没有浏览器支持它们全部。 因此,要立即开始实施HTML5标准组件,可以从提供缺少功能的两个开源项目中进行选择:Polymer和X-Tags。

本文向您展示如何:

  • 将组件标记封装在Shadow DOM中。
  • 从惰性HTML模板中删除实时DOM元素。
  • 创建自定义元素并将其连接到JavaScript。
  • 导入HTML文件。
  • 用Polymer实现组件。
  • 使用X标签实现组件。

影子DOM

图1显示了播放视频HTML5应用程序以及Chrome的Elements检查器(位于Tools-> Developer tools下 ),该检查器显示了video元素内的元素:

图1. video元素内部
Chrome的屏幕截图,显示了元素检查器叠加在视频上。

请注意,即使很明显, video元素包含播放/暂停按钮,进度指示器和其他元素,元素检查器也仅在video元素内显示单个source元素。 您看不到它们,因为它们位于Shadow DOM中,默认情况下不可见。 图2显示了如何在Chrome的Elements检查器中显示Shadow DOM元素:

图2.在Chrome中启用影子DOM
Chrome开发人员工具中的设置对话框的屏幕截图,您可以在其中通过选中显示阴影DOM复选框在Chrome中启用阴影DOM

要进入图2所示的设置对话框,请点击Chrome开发者工具窗口右下角的齿轮图标。 向下滚动到Show Shadow DOM复选框。 选中该框后,Chrome的Elements检查器会在阴影DOM中显示元素,如图3所示:

图3.查看video元素的影子DOM
在Chrome的Elements检查器中查看视频元素的影子DOM的屏幕截图

图1相似, 图3显示了video元素内部的元素,但是这次由于Chrome正在显示Shadow DOM元素,因此video元素的内部可见。

Shadow DOM(直到最近才仅对浏览器实现者可用)对应用程序开发人员很有用,因为默认情况下,Shadow DOM元素不可被周围的DOM树访问且不受其影响。 因为它们本质上封装在自己的世界中,所以其他组件不会干扰它们的工作方式 。

图4显示了一个人为设计示例的结果,该示例说明了如何将元素放入Shadow DOM:

图4.更改按钮的影子根
更改了按钮的影子根的应用程序的屏幕截图

该应用程序的启动类似于图4左侧的屏幕截图,其中仅显示标题和按钮。 如果单击按钮,则应用程序将使用位于按钮的Shadow DOM中的图片和标题(如右图所示)替换文本。

清单1显示了图4所示的应用程序HTML:

清单1.填充按钮的Shadow DOM
<!DOCTYPE html>
<html>
   <head>
      <title>Shadow DOM</title>

      <style>
        button {
           font: 18px Century Schoolbook;
           border: thin solid gray;
           background: rgba(200, 200, 200, 0.5);
           padding: 10px;
        }
      </style>
   </head>

   <body>
      <h1>Shadow DOM</h1>

      <button id='button'>Click this button</button>

      <script>
         var b = document.getElementById('button');

         b.onclick = function (e) {
            var sr = b.webkitCreateShadowRoot();

            sr.innerHTML = '<p>This content is in the shadow DOM</p>' +
                            '<img src="beach.png">';
         };
      </script>
   </body>
</html>

当应用程序在浏览器中加载时, 清单1底部JavaScript运行,创建一个onclick事件处理程序,该事件处理程序使用webkitCreateShadowRoot()方法创建阴影根 ,即阴影DOM树中的顶部节点。 然后,事件处理程序使用两个元素填充该阴影根:一个段落和一个图像。

每当为元素创建影子根目录并随后设置元素的内部HTML时,都将覆盖元素的原始内容, 如图4中的应用程序所示。

默认情况下,按钮没有Shadow DOM,因此浏览器允许您创建一个按钮,如清单1所示 。 但是对于默认情况下已经具有Shadow DOM的元素(例如video元素),浏览器并不那么适应。 如图5所示, sr = b.webkitCreateShadowRoot(); 导致Chrome元素检查器发出不属于该节点的错误消息:

图5.尝试(失败)更改video元素的阴影根
Chrome元素检查器的屏幕截图,显示了您尝试为视频元素创建Shadow DOM时出现的错误消息

模板,自定义元素和HTML导入

既然您已经看到了Shadow DOM的实际应用,我将把它与HTML5 Web组件的其他主要组成部分一起实用地使用:模板,自定义元素和HTML导入。

图6显示了HTML5丹佛聚会组中的聚会的简单无序列表:

图6.聚会的无序列表
屏幕快照的无序聚会

清单2显示了在图6中创建无序列表的标记:

清单2.无序聚会HTML
<!DOCTYPE html>
<html>
<head>
    <title>Meetups Component</title>
    
</head>
<body>

   <ul>
     <li class="mobile">Sencha Touch. 
        <span class='date'>Jan 23</span></li>

     <li class="html5-in-general">HTML5 & Semantic Markup. 
        <span class='date'>Jun 18</span></li>

     <li class="html5-in-general">HTML5 & Windows 8. 
        <span class='date'>Jul 23</span></li>

     <li class="javascript">HTML5 JavaScript on Crack. 
        <span class='date'>Aug 20</span></li>

     <li class="javascript">CoffeeScript for Recovering JavaScript Programmers. 
        <span class='date'>Sept 17</span></li>

     <li class="html5-in-general">ClojureScript and CouchDB. 
        <span class='date'>May 21</span></li>

     <li class="html5-in-general">Polyfills for the Pragmatist. 
        <span class='date'>Apr 23</span></li>

     <li class="design">CSS3 for Programmers. 
        <span class='date'>Feb 20</span></li>

     <li class="lightning">Quick-start web apps; 
     Graphics; Data visualization; Adaptive patterns; JSON. 
        <span class='date'>Oct 22</span></li>

     <li class="lightning">Web workers; CSS3; HTTP; Audio, video, & canvas; 
     Charting; JS evolution. 
        <span class='date'>March 19</span></li>
   </ul>

</body>
</html>

清单2HTML没什么变化。 它只是创建带有列表项的单个无序列表。 图7显示了相同的列表项,但不是驻留在无序列表中,而是位于自定义组件内部并由其操作:

图7.一个定制的meetup列表组件
由自定义的Meetup-List组件生成的Meetup列表的屏幕截图

清单3显示了图7所示的应用程序的标记:

清单3. Meetup-talks组件而不是无序列表
<!DOCTYPE html>
<html>
<head>
    <title>Meetups Component</title>
    <script src="../polymer/polymer.js"></script>
    <link rel="components" href="meetup-component.html">

</head>
<body>

   <meetup-talks>
     <li class="mobile">Sencha Touch. 
        <span class='date'>Jan 23</span></li>

     <li class="html5-in-general">HTML5 & Semantic Markup. 
        <span class='date'>Jun 18</span></li>

     <li class="html5-in-general">HTML5 & Windows 8. 
        <span class='date'>Jul 23</span></li>

     <li class="javascript">HTML5 JavaScript on Crack. 
        <span class='date'>Aug 20</span></li>

     <li class="javascript">CoffeeScript for Recovering JavaScript Programmers. 
        <span class='date'>Sept 17</span></li>

     <li class="html5-in-general">ClojureScript and CouchDB. 
        <span class='date'>May 21</span></li>

     <li class="html5-in-general">Polyfills for the Pragmatist. 
        <span class='date'>Apr 23</span></li>

     <li class="design">CSS3 for Programmers. 
        <span class='date'>Feb 20</span></li>

     <li class="lightning">Quick-start web apps; 
     Graphics; Data visualization; Adaptive patterns; JSON. 
        <span class='date'>Oct 22</span></li>

     <li class="lightning">Web workers; CSS3; HTTP; Audio, video, & canvas; 
     Charting; JS evolution. 
        <span class='date'>March 19</span></li>
   </meetup-talks>

</body>
</html>

注意清单3的标记与清单2的标记几乎相同,但有三个区别:

  • 清单3中的标记包括一个名为polymer.js的文件。 该文件与Polymer开源项目一起提供,该项目提供HTML 5 Web组件API(阴影DOM,模板等)的实现。 我将在下一节的“ 聚合物”部分中详细讨论的“聚合物”项目由Chrome开发团队实施。
  • 清单3使用link元素导入另一个HTML5文件。 对link元素的使用被称为HTML import 。 在撰写本文时,还没有任何浏览器实现HTML导入。 在此示例中,该功能来自Polymer项目。
  • 清单2中的无序列表元素替换为清单3中meetup-talks定制元素。

meetup-talks定制元素在metup-component.html中实现,如清单4所示:

清单4. meetup-list元素
<element name="meetup-list">
  <template>
    <style>
      /* styles that follow only apply to the ShadowDOM of the <meetup-list> element */

      #meetups {
        display: block;
        padding: 15px;
        padding-top: 0px;
        background: lightgray;
        border: thin solid cornflowerblue;
      }

      .title {
        color: blue;
        font-size: 1.5em;
      }
    </style>

    <div id='meetups'>
      <p class='title'>HTML5 in General</p>
      <content select='.html5-in-general'></content>
    
      <p class='title'>JavaScript</p>
      <content select='.javascript'></content>
    
      <p class='title'>Design</p>
      <content select='.design'></content>
    
      <p class='title'>Lightning</p>
      <content select='.lightning'></content>
    </div>
  </template>

  <script>
    Polymer.register(this);
  </script>
</element>

清单4是使事情变得有趣的地方。 首先,我声明一个名称为meetup-list的新元素,并小心地在HTML规范要求的名称中包括一个连字符。 在清单的最后,一行JavaScript向Polymer全局对象注册了meetup-list元素。 这需要声明和注册自定义元素,以便可以在HTML页面中使用它。

element元素内部,我声明一个template 。 模板以声明方式而非编程方式定义了Shadow DOM。 因此,在清单4中 ,我创建了一个Shadow DOM模板。 每当有人在HTML页面中使用meetup-list元素时,浏览器就会使用该Shadow DOM模板为该元素标记(创建)新的Shadow DOM实例。

在模板内部,我定义了两种CSS样式,它们仅适用于template中的元素 。 反过来说,由于模板代表了Shadow DOM,因此在周围文档中定义CSS样式不会影响模板中的元素 。 例如,如果要为清单3中HTML添加段落元素的样式,则该样式不会影响模板中的段落。

除了CSS样式外,模板还定义了随后的Shadow DOM实例中的元素。 content元素使用CSS选择器从meetup-list 原始内容中选择列表项。 因此,模板除了以声明方式指定Shadow DOM实例外,还可以有选择地将元素的原始内容插入模板本身 。 请注意,您可以使用<content></content>将元素的全部原始内容插入其模板。

立即实施Web组件

我在本文中讨论的所有Web组件API都是相对较新的,浏览器供应商之间提供了不同程度的支持。 为了今天有效地实现组件,您不仅可以编写代码并将其加载到浏览器中; 相反,您需要HTML5业务中称为polyfills或shims的解决方案:可以使用新功能的解决方案(如果可用),而不能使用新功能。

当前,有两个项目提供Web组件polyfill:Polymer和Mozilla X-Tags。 Polymer仅适用于Chrome,并且要求网络服务器使用HTML导入,因此不适合生产使用。 X-Tags几乎可以与所有现代浏览器一起使用,并且不需要Web服务器。 但是,X-Tags仅实现自定义元素API,而没有模板和Shadow DOM。

接下来,我向您展示如何分别使用Polymer和X-Tags将标准组件包装在我在本系列的前几篇文章中实现的即席滑块周围。

聚合物

根据定义,临时组件不遵循组件标准,因此没有实现或使用它们的标准方法。 但是,通过将它们包装在标准组件中,可以使它们更易于使用。 首先,我使用Polymer将临时滑块包装在标准组件中。 图8显示了Polymer版本的滑块:

图8.聚合物滑块
用Polymer实现的滑块的屏幕截图

清单5显示了如何使用Polymer版本的滑块:

清单5.使用Polymer滑块标签
<!DOCTYPE html>
<html>
   <head>
      <title>Slider with Polymer</title>
    <script src="../polymer/polymer.js"></script>
    <script src="lib/slider.js"></script>
    <link rel="import" href="./slider.html" />
   </head>
   
   <body>
     <x-slider id='slider'
                fillColor='goldenrod'
                strokeColor='red'>
     </x-slider>
   </body>
</html>

如果将本系列的第一篇文章中的清单5清单2进行比较,它展示了如何单独使用临时滑块,那么您会发现清单5非常简单。 使用x-slider聚合物元素,您可以使用一行HTML创建一个滑块。

清单6中实现了x-slider element

清单6. Polymer滑块组件
<element name="x-slider" attributes="strokeColor fillColor">
  <template>
    <style>
       x-slider {
          display: block;
       }

       .x-slider-button {
          float: left;
          margin-left: 2px;
          margin-top: 5px;
          margin-right: 5px;
          vertical-align: center;
          border-radius: 4px;
          border: 1px solid rgb(100, 100, 180);
          background: rgba(255, 255, 0, 0.2);
          box-shadow: 1px 1px 4px rgba(0,0,0,0.5);
          cursor: pointer;
          width: 25px;
          height: 20px;
       }

       .x-slider-button:hover {
          background: rgba(255, 255, 0, 0.4);
       }

       #xSliderDiv {
          position: relative;
          float: right;
          width: 80%;
          height: 65%;
       } 
    </style>

    <div id='x-slider-buttons-div' 
         style='width: {{width}}px; height: {{height}}px;'>

       <button class='x-slider-button' id='xSliderMinusButton'>-</button>
       <button class='x-slider-button' id='xSliderPlusButton'/>+</button>
       <div id='xSliderDiv'></div>

    </div>
  </template>

  <script>
    Polymer.register(this, {
        width: 350,
        height: 50,
        strokeColor: 'blue',
        fillColor: 'cornflowerblue',

        ready: function () { 
          var self = this,
              slider = new COREHTML5.Slider(this.strokeColor, 
                                            this.fillColor, 0);

          setTimeout( function () { // This timeout is a hack
            slider.appendTo(self.$.xSliderDiv);
            slider.draw();
          }, 200);

          this.$.xSliderMinusButton.onclick = function () {
            if (slider.knobPercent >= 0.1) {
              slider.knobPercent -= 0.1;
              slider.erase();
              slider.draw();
            }
          };

          this.$.xSliderPlusButton.onclick = function () {
            if (slider.knobPercent <= 0.9) {
              slider.knobPercent += 0.1;
              slider.erase();
              slider.draw();
            }
          };
        }
    });

  </script>
</element>

清单6清单4相似。 这两个清单都定义了一个新元素,并将该元素注册到Polymer全局对象。 两者都定义了一个包含CSS样式和标记的模板。 清单6清单4的区别在于清单6对Polymer数据绑定和ready事件处理程序的使用。

双胡子符号(如{{width}}符号)表示元素属性。 您可以在元素的标记中使用双胡子符号。 在清单6中 ,我将元素包围的DIV的宽度和高度设置为页面作者使用元素属性设置的宽度和高度。

您可以在传递给Polymer.register()方法的对象中声明属性; 例如, 清单6x-slider元素声明了四个属性: widthheightstrokeColorfillColor 。 如果使用element元素的attributes属性指定属性(称为发布属性) ,则页面作者可以在其元素中使用这些属性,如清单5中x-slider元素一样。

根据Polymer文档, 当组件完成对自身的初始化后 ,如果存在,它将调用其ready()方法。 该文档没有进一步详细说明组件何时进行初始化,而是显然是在浏览器准备绘制组件之前。 由于组件在绘制之前就已初始化,并且因为ready()方法是当前生命周期中的唯一方法,所以我不得不添加一个setTimeout() hack,该方法在ready()方法之后200ms绘制滑块被调用。 这样的粗糙边缘无疑会随着时间的流逝而平滑。 (Web组件规范还定义了一个inserted回调,浏览器在将元素插入DOM之后会被浏览器调用,但是在发布本文时,Polymer不支持该回调。)

Polymer还为自定义元素提供了$属性,该属性引用了元素属性的映射。 我使用该地图访问最终包含临时滑块的DIV

X标签

滑块的X-Tags版本如图9所示:

图9. X-Tags滑块组件
X标记实现的滑块的屏幕截图

滑块的Polymer和X-Tags实现在视觉上是无法区分的。 我用不同的颜色实现它们只是为了说明它们是用不同的框架实现的。 清单7显示了图9所示的应用程序如何使用滑块的X-Tags版本(也实现为x-slider ):

清单7.使用X-Tags滑块组件
<!DOCTYPE html>
<html>
   <head>

      <title>Slider with x-tag</title>
      <link rel="stylesheet" type="text/css" href="x-slider.css" />
   </head>
   
   <body>
      <x-slider id='slider'
                slider-fill-color='rgba(50, 105, 200, 0.8)'
                slider-stroke-color='navy'>
      </x-slider>
   </body>

   <script type="text/javascript" src="lib/x-tag.js"></script>
   <script type="text/javascript" src="lib/slider.js"></script>
   <script type="text/javascript" src="x-slider.js"></script>
</html>

清单7清单5相似。 这两个清单都使用一个简单的x-slider元素在页面中放置一个滑块。 区别在于Polymer版本使用HTML导入来包含定义滑块HTML片段,而X-Tags版本则包含JavaScript,因为它不支持HTML导入。

清单8显示了实现该组件JavaScript:

清单8.滑块JavaScript
function getFirstAncestor(name, startingElement) {
   var  element = startingElement
      , localName = element.localName;

   while (localName !== name) {
      element = element.parentNode;
      localName = element.localName;
   }

   return element;
};
   
function getSlider(element) {
   return getFirstAncestor('x-slider', element).slider;
};
   
xtag.register('x-slider', { 
   onCreate: function () { 
      var content =
             "<div id='x-slider-buttons-div'>"                                          +
                "<button class='x-slider-button' id='x-slider-minus-button'>-</button>" +
                "<button class='x-slider-button' id='x-slider-plus-button'>+</button>"  +
             "</div>"                                                                   +
             ""                                                                         +
             "<div id='x-slider-slider-div'></div>"                                     +
             ""                                                                         +
             "<div id='x-slider-readout-div'></div>";

          stroke = this.getAttribute('slider-stroke-color'),
          fill   = this.getAttribute('slider-fill-color');
 
         // 'this' is the x-slider HTML element

         this.max = 100;

         this.innerHTML = content;
         this.slider = new COREHTML5.Slider(stroke, fill, 0);

         this.slider.appendTo('x-slider-slider-div');
         this.slider.draw();
      },

      events: {
         'click:touch:delegate(#x-slider-plus-button)': function(event, slider) {
            var slider = getSlider(this)  // 'this' is the button
               , value = getFirstAncestor('x-slider', this).getValue();
               
            if (slider.knobPercent <= 0.9) {
               slider.knobPercent += 0.1;
            }
            slider.erase();
            slider.draw();

            console.log(value);
         },

         'click:touch:delegate(#x-slider-minus-button)': function(event, slider) {
            var slider = getSlider(this)  // 'this' is the button
               , value = getFirstAncestor('x-slider', this).getValue();

            if (slider.knobPercent >= 0.1) {
               slider.knobPercent -= 0.1;
            }
            slider.erase();
            slider.draw();

            console.log(value);
         },
      },

      methods: {
         getValue: function () {
            // 'this' is the x-slider HTML element
            return this.slider.knobPercent * this.max; 
         }
      }
});

清单8中用X-Tags定义组件与清单6中用Polymer定义组件完全不同。 X-Tags纯粹在JavaScript中定义元素,这涉及使用字符串连接并设置元素的内部HTML来设置自定义元素的内容。 与Polymer形成鲜明对比的是Polymer,它以更易读和可维护HTML定义了自定义元素的内容。

X-Tags没有像Polymer的$这样的属性,可以轻松访问自定义元素中的元素,因此我必须实现getFirstAncestor()函数来访问包含临时滑块的元素。

最后,X-Tags支持实现事件以处理控制滑块旋钮的按钮的单击。 但是,对于本次练习而言,这种支持对我而言似乎是过大的。

为了完整起见,清单9中显示了滑块的X-Tags版本CSS:

清单9.滑块CSS
x-slider {
   display: block;
}

.x-slider-button {
   float: left;
   margin-left: 2px;
   margin-top: 15px;
   margin-right: 5px;
   vertical-align: center;
   border-radius: 4px;
   border: 1px solid rgb(100, 100, 180);
   background: rgba(255, 255, 0, 0.2);
   box-shadow: 1px 1px 4px rgba(0,0,0,0.5);
   cursor: pointer;
   width: 25px;
   height: 20px;
}

.x-slider-button:hover {
   background: rgba(255, 255, 0, 0.4);
}

#x-slider-buttons-div {
   width: 25%;
   height: 100%;
} 

#x-slider-slider-div {
   position: relative;

   float: right;
   margin-top: -40px;
   width: 80%;
   height: 65%;
}

结论

当前,JavaScript框架主要实现临时组件,这些组件遵循专有API而非标准。 结果,每当您迁移到新框架时,您都将面临巨大的学习曲线。 而且由于临时组件通常没有被封装,因此其功能可能会受到应用程序中其他组件的不利影响。

在本系列文章中 ,您已经了解了如何使用HTML5 API来实现标准组件和即席组件。 用于实现组件HTML5规范是相对较新的,浏览器供应商之间的支持也不同。 您可以立即开始实施标准组件,但是您需要的不仅仅是浏览器。 在本文中,我简要讨论了两个框架,即Polymer和X-Tag,它们使实现标准组件成为可能。

随着Web组件规范的成熟以及浏览器供应商实现其功能,我们很快将拥有一个可行的平台来构建标准组件。 然后,实现HTML5应用程序将比今天更加有趣。


翻译自: https://www.ibm.com/developerworks/web/library/wa-html5components3/index.html

windows标准组件调用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值