Polymer - Shadow DOM 和样式
Shadow DOM 是用于构建组件的 DOM 新属性。
示例
在下面的代码中,header 组件包括页面标题和菜单按钮。
<header-demo>
<header>
<h1>
<button>
Shadow DOM 允许将子项定位在范围子树中,这被称为影子树。
<header-demo>
#shadow-root
<header>
<h1>
<button>
shadow-root 根被称为影子树的顶部,而附加到树上的元素称为影子主机 (header-demo)。此影子主机包含一个名为 shadowRoot 的属性,该属性指定影子根。影子根使用主机属性标识主机元素。
影子 DOM 和组合
如果影子 DOM 中有一个元素,则可以渲染影子树而不是元素的子元素。可以通过将 <slot> 元素添加到影子树来渲染元素的子元素。
例如,对 <header-demo> 使用以下影子树。
<header> <h1><slot></slot></h1> <button>Menu</button> </header>
将子元素作为 − 添加到 <my-header> 元素
<header-demo>Shadow DOM</header-demo>
header 使用上面指定的子元素替换 </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>
多级分布
您可以将 slot 元素分配给一个 slot,这称为多级分布。
例如,取影子树的两个级别,如下所示 −
<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">
//它指定元素本地 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 样式
您可以使用样式属性来设置 shadow DOM 的样式,这些属性从主机继承到 shadow 树。
示例
<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 选择器设置主机元素的样式(附加到 Shadow 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/。以下是输出。
样式化插槽内容
可以在元素模板中创建插槽,这些插槽在运行时被占用。
示例
以下示例描述了在元素模板中使用插槽内容。创建一个 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>
现在,再创建一个名为 colors-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>

