Polymer - Shadow DOM 和样式


Shadow DOM 是用于构建组件的 DOM 的新属性。

例子

在下面的代码中,标题组件包括页面标题和菜单按钮。

<header-demo>
   <header>
      <h1>
         <button>

Shadow DOM 允许在作用域子树中定位子级,该子树称为影子树

<header-demo>
   #shadow-root
   <header>
      <h1>
      <button>

Shadow-Root根称为影子树的顶部,附加到树的元素称为影子主机(header-demo)。该影子主机包含一个名为shadowRoot 的属性,用于指定影子根。影子根使用主机属性来标识主机元素。

Shadow DOM 和组合

如果 Shadow DOM 中有一个元素,则可以渲染 Shadow 树而不是元素的子元素。可以通过将 <slot> 元素添加到影子树来渲染该元素的子元素。

例如,将以下影子树用于 <header-demo>。

<header>
   <h1><slot></slot></h1>
   <button>Menu</button>
</header>

将子元素添加到 <my-header> 元素中:

<header-demo>Shadow DOM</header-demo>

标头将 </slot> 元素替换为上面指定的子元素:

<header-demo>
   <header>
      <h1>Shadow DOM</h1>
      <button>Menu</button>
   </header>
</header-demo>

后备内容

当没有节点分配给该槽时,可以显示后备内容。例如 -

<my-element>
   #shadow-root
   <slot id = "myimgicon">
      <img src = "img-demo.png">
   </slot>
   <slot></slot>
<my-element>

您可以为元素提供自己的图标:

<my-element>
   <img slot = "myimgicon" src = "warning.png">
<my-element>

多级分布

可以将槽元素分配给一个槽,这就是所谓的多级分配。

例如,采用影子树的两个级别,如下所示 -

<parent-element>
   #shadow-root
      <child-element>
      <!-- display the light DOM children of parent-element inside child-element -->
      <slot id = "parent-slot">
	  
   <child-element>
      #shadow-root
         <div>
            <!-- Render the light DOM children inside div by using child-element -->
            <slot id = "child-slot">

考虑以下代码 -

<parent-element>
   <p>This is light DOM</p>
<parent-element>

扁平树的结构如下所示。

<parent-element>
   <child-element>
      <div>
         <slot id = "child-slot">
            <slot id = "parent-slot">
               <p>This is light DOM</p>

Shadow DOM 使用以下 Slot API 来检查分布 -

  • HTMLElement.assignedSlot - 它为元素分配槽,如果没有为槽分配元素,则返回 null。

  • HTMLSlotElement.assignedNodes - 当您将 flatten 选项设置为 true 时,它​​提供节点列表以及插槽并返回分布式节点。

  • HTMLSlotElement.slotchange - 当插槽的分布式节点发生变化时触发此事件。

事件重定向

它指定事件的目标,其中元素可以在与侦听元素相同的范围内表示。它提供来自自定义元素的事件,该事件看起来像是来自自定义元素标记,而不是来自其中的元素。

例子

以下示例显示了 Polymer.js 中事件重定向的使用。创建一个名为index.html的文件并将以下代码放入其中。

<!doctype html>
<html>
   <head>
      <title>Polymer Example</title>
      <script src = "bower_components/webcomponentsjs/webcomponents-lite.js"></script>
      <link rel = "import" href = "bower_components/polymer/polymer.html">
      <link rel = "import" href = "retarget-event.html">
   </head>
   
   <body>
      <template id = "myapp" is = "dom-bind">
         <retarget-event on-tap = "clicky"></retarget-event>
      </template>
      
      <script>
         var myval = document.querySelector('#myapp');
         myval.clicky = function(e) {
            console.log("The retargeted result:", Polymer.dom(myval));
            console.log("Normal result:", e);
         };
      </script>
   </body>
</html>

现在,创建另一个名为 retarget-event.html 的文件并包含以下代码。

<link rel = "import" href = "bower_components/polymer/polymer-element.html">

//it specifies the start of an element's local DOM
<dom-module id = "retarget-event">

   <template>
      <span>Click on this text to see result in console...</span>
   </template>

   <script>
      Polymer ({
         is: 'retarget-event',
      });
   </script>
</dom-module>

输出

要运行该应用程序,请导航到创建的项目目录并运行以下命令。

polymer serve

现在打开浏览器并导航到http://127.0.0.1:8081/。以下将是输出。

聚合物重定向事件

单击上面的文本并打开控制台以查看重定向事件,如以下屏幕截图所示。

聚合物重定向事件

Shadow DOM 样式

您可以使用从宿主继承到影子树的样式属性来设置影子 DOM 的样式。

例子

<style>
   .mydemo { background-color: grey; }
</style>

<my-element>
#shadow-root
   <style>
      //this div will have blue background color
      div { background-color: orange; }
   </style>
   <div class = "mydemo">Demo</div>

DOM 模板

可以使用 DOM 模板为元素创建 DOM 子树。您可以为元素创建影子根,并通过将 DOM 模板添加到元素来将模板复制到影子树中。

DOM 模板可以通过两种方式指定 -

  • 创建一个 <dom-module> 元素,该元素应与元素的名称以及 id 属性相匹配。

  • 在 <dom-module> 内定义一个 <template> 元素。

例子

<dom-module id = "my-template">
   <template>I am in my template!!!</template>

   <script>
      class MyTemplate extends Polymer.Element {
         static get is() { return  'my-template' }
      }
      customElements.define(MyTemplate.is, MyTemplate);
   </script>
</dom-module>

设置元素 Shadow DOM 的样式

Shadow DOM 允许使用字体、文本颜色和类等样式属性来设置自定义元素的样式,而无需将其应用到元素的范围之外。

让我们使用:host选择器设置宿主元素的样式(附加到影子 DOM 的元素称为宿主)。创建一个名为polymer-app.html 的文件并在其中添加以下代码。

<link rel = "import" href = "../../bower_components/polymer/polymer-element.html">

<dom-module id = "polymer-app">
   <template>
      <style>
         :host {
            color:#33ACC9;
         }
      </style>
      <h2>Hello...[[myval]]!</h2>	
  </template>

  <script>
      class PolymerApp extends Polymer.Element {
         static get is() { return 'polymer-app'; }
         static get properties() {
            return {
               myval: {
                  type: String, value: 'Welcome to Tutorialspoint!!!'
               }
            };
         }
      }

      window.customElements.define(PolymerApp.is, PolymerApp);
   </script>
</dom-module>

如上一章所示运行应用程序并导航到http://127.0.0.1:8000/。以下将是输出。

聚合物阴影 DOM 样式

样式开槽内容

可以在元素的模板中创建槽,这些槽在运行时被占用。

例子

以下示例描述了元素模板中开槽内容的使用。创建一个index.html文件并在其中添加以下代码。

<!doctype html>
<html>
   <head>
      <title>Polymer Example</title>
      <link rel = "import" href = "bower_components/polymer/polymer.html">
      <link rel = "import" href = "slotted-content.html">
   </head>
   
   <body>
      <slotted-content>
         <div slot = "text">This is Polymer.JS Slotted Content Example</div>
      </slotted-content> 
   </body>
</html>

现在创建另一个名为 slotted-content.html 的文件并包含以下代码。

<link rel = "import" href = "bower_components/polymer/polymer-element.html">

<dom-module id = "slotted-content">
   <template>
      <style>
         ::slotted(*) {
            font-family: sans-serif;
            color:#E94A9D;
         }
      </style>
      
      <h2>Hello...[[prop1]]</h2>
      <h3>
         <div><slot name='text'></slot></div>
      </h3>
   </template>
   
   <script>
      Polymer ({
         is: 'slotted-content', properties: {
            prop1: {
               type: String,
               value: 'Welcome to Tutorialspoint!!',
            },
         },
      });
   </script>
</dom-module>

如上例所示运行应用程序,然后导航到http://127.0.0.1:8081/。以下将是输出。

聚合物样式开槽内容

使用样式模块

您可以与样式模块一起在元素之间共享样式。在样式模块中指定样式,并在元素之间共享它们。

例子

以下示例展示了如何在元素之间使用样式模块。创建一个index.html文件并在其中添加以下代码。

<!doctype html>
<html>
   <head>
      <title>Polymer Example</title>
      <link rel = "import" href = "bower_components/polymer/polymer.html">
      <link rel = "import" href = "style-module.html">
   </head>
   
   <body>
      <style-module></style-module> 
   </body>
</html>

使用以下代码创建另一个名为 style-module.html 的文件。

<link rel = "import" href = "bower_components/polymer/polymer-element.html">

<dom-module id = "style-module">
   <template>
      <!-- here, including the imported styles from colors-module page -->
      <style include="colors-module"></style>
      <style>
         :host {
            font-family: sans-serif;
            color: green;    
         }
      </style>
      
      <h2>Hello...[[prop1]]</h2>
      <p class = "color1">Sharing styles with style modules 1...</p>
      <p class = "color2">Sharing styles with style modules 2...</p>
      <p class = "color3">Sharing styles with style modules 3...</p>
   </template>
   
   <script>
      Polymer ({
         is: 'style-module', properties: {
            prop1: {
               type: String, value: 'Welcome to Tutorialspoint!!',
            },
         },
      });
   </script>
</dom-module>

现在,再创建一个名为color-module.html 的文件,它为元素提供样式模块,如以下代码所示。

<link rel = "import" href = "bower_components/polymer/polymer-element.html">

<dom-module id = 'colors-module'>
   <template>
      <style>
         p.color1 {
            color: #EA5AA5;
         }
         p.color2 {
            color: #4B61EA;
         }
         p.color3 {
            color: #D3AA0A;
         }
      </style>
   </template>
</dom-module>

运行应用程序并导航到http://127.0.0.1:8081/。以下将是输出。

聚合物型模块

使用自定义属性

自定义 CSS 属性可用于使用 Polymer 元素来设置应用程序中元素的外观样式。自定义属性提供级联 CSS 变量,这些变量可以在自定义元素的环境之外使用,从而避免通过样式表分散样式数据。

自定义属性可以像标准 CSS 属性一样定义,这些属性继承自组合的 DOM 树。在前面的示例中,您可以看到为元素定义的自定义 CSS 属性。

在CSS继承下,如果没有为某个元素定义样式,那么它将从其父元素继承样式,如下代码所示。

<link rel = "import" href = "components/polymer/myelement-style.html">
<myelement-style>
   <style is = "myelement-style">
      p {
         color: var(--paper-red-900);
      }
      paper-checkbox {
         --paper-checkbox-checked-color: var(--paper-red-900);
      }
   </style>
</myelement-style>

<body>
   <p><paper-checkbox>Check Here</paper-checkbox></p>
</body>