You're viewing an older version of Polymer. Please see Polymer 3.0 for the latest.

Polymer 使声明性地创建 Web 组件变得简单。

新的 Web 开发者能够简单地使用标记来添加自定义 HTML 元素到一个网页上去。这就像您已经熟悉的使用 HTML 标签的用法一样:

<h1>A heading!</h1>
<fancy-thing>A fancy thing!</fancy-thing>

有经验的 Web 开发者能够使用 Polymer 的特殊功能来减少样板代码,使构建复杂的、交互的元素变得更容易。 在这个教程中,您将学会如何:

  • 注册元素
  • 使用生命周期回调
  • 观察属物
  • 使用模板创建阴影 DOM
  • 使用数据绑定

在本节中,您可以快速浏览 Polymer 库,而无需安装任何内容。单击 在Plunker上编辑 按钮打开交互式沙箱中的任何示例。

点击每个功能后面的按钮了解更多信息。

Plunker 示例无法运行于 Internet Explorer 11。 These code samples need to be transpiled from ES6 to ES5 to work in Internet Explorer. This is usually done as a build step. At the moment, we don't have a way to transpile the interactive samples on Plunker. The samples will work in browsers that support ES6 - for example, the latest versions of Chrome, Edge, Firefox and Safari.

要注册一个新元素,创建 ES6 类扩展 Polymer.Element,然后调用 customElements.define 方法,该方法在浏览器中 注册 一个新的元素。 注册元素将元素名称与类相关联,因此您可以向自定义元素添加属物和方法。自定义元素的名称 必须以ASCII字母开头,并包含连接号(-)

custom-element.html
<link rel="import"  href="https://polygit.org/components/polymer/polymer-element.html">

<script>
  // 为一个新的叫做 custom-element 的元素定义类
  class CustomElement extends Polymer.Element {
    static get is() { return "custom-element"; }
    constructor() {
        super();
        this.textContent = "我是一个自定义元素。";
      }
  }
  // 在浏览器中注册这个新的元素
  customElements.define(CustomElement.is, CustomElement);
</script>

index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://polygit.org/components/webcomponentsjs/webcomponents-loader.js"></script>
    <link rel="import" href="custom-element.html">
  </head>
  <body>
    <custom-element></custom-element>
  </body>
</html>

Plunker 上尝试:

  • 尝试更改 this.textContent 的内容。
  • 如果您熟悉您的浏览器的开发者工具,尝试在控制台里面打印该自定义元素的 tagName 属物。 提示:添加 console.log(this.tagName); 到构造方法里!

此示例使用一个生命周期回调把内容添加到 <custom-element> 上,在它初始化完成时。 当自定义元素完成其初始化时,ready 生命周期回调被调用。 您可以使用 ready 回调进行一次性的初始化工作,在元素被创建以后。

了解更多:元素注册

了解更多:生命周期回调

许多元素包括一些内部 DOM 节点来实现元素的 UI 和行为。您可以使用 Polymer 的 DOM 模板化为元素创建一个阴影 DOM 树。

dom-element.html
<link rel="import"  href="https://polygit.org/components/polymer/polymer-element.html">

<dom-module id="dom-element">

  <template>
    <p>我是一个 DOM 元素。这是我的阴影 DOM !</p>
  </template>

  <script>
    class DomElement extends Polymer.Element {
      static get is() { return "dom-element"; }
    }
    customElements.define(DomElement.is, DomElement);
  </script>

</dom-module>

index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://polygit.org/components/webcomponentsjs/webcomponents-loader.js"></script>
    <link rel="import" href="dom-element.html">
  </head>
  <body>
    <dom-element></dom-element>
  </body>
</html>

Plunker 上尝试:

  • 尝试在 块中添加一些其他 HTML 元素。例如,添加 <h1>A heading!</h1><a href=”stuff.html”>A link!</a>

阴影 DOM 被封装在元素内。

了解更多:DOM 模板化

阴影 DOM 可让您控制 构造。元素的子元素可以是 分布式的 以让它们可以被渲染成像被插入到阴影 DOM 树中一样。

此示例创建一个简单的标签,通过使用一个样式化的 <div> 标签来包装一个图片来装饰该图片。

picture-frame.html
<link rel="import"  href="https://polygit.org/components/polymer/polymer-element.html">

<dom-module id="picture-frame">

  <template>
    <!-- 该元素作用域的 CSS -->
    <style>
      div {
        display: inline-block;
        background-color: #ccc;
        border-radius: 8px;
        padding: 4px;
      }
    </style>
    <div>
      <!-- 所有子元素渲染到这里 -->
      <slot></slot>
    </div>
  </template>

  <script>
    class PictureFrame extends Polymer.Element {
      static get is() { return "picture-frame"; }
    }
    customElements.define(PictureFrame.is, PictureFrame);
  </script>

</dom-module>
index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://polygit.org/components/webcomponentsjs/webcomponents-loader.js"></script>
    <link rel="import" href="picture-frame.html">
  </head>
  <body>
    <picture-frame>
      <img src="https://www.polymer-project.org/images/logos/p-logo-32.png">
    </picture-frame>
  </body>
</html>

Plunker 上尝试:

  • 尝试添加 <div>index.html;它是否受 <picture-frame> 的阴影 DOM 里的样式影响?
  • 尝试添加其他 HTML 元素到 DOM 模板中,以观察它们如何相对于那些分布的子节点来定位。

注意: <dom-module> 里面定义的 CSS 样式的 作用域 仅限于元素的阴影 DOM。 所以这里的 div 规则仅仅影响 <picture-frame> 里的 <div> 标签。

了解更多:构造和分布

当然,静态阴影 DOM 还不够。您通常想让您的元素动态地更新它的阴影 DOM。

数据绑定是快速传播元素内改变并减少样板代码的好方法。 您可以使用“双胡子”语法 ({{}}) 来绑定组件中的属物。 这 {{}} 由大括号中引用的属物的值所替换。

name-tag.html
<!-- 导入 polymer-element -->
<link rel="import"  href="https://polygit.org/components/polymer/polymer-element.html">

<dom-module id="name-tag">
  <template>
    <!-- 绑定到 "owner" 属物 -->
    这是 <b>{{owner}}</b> 的 name-tag 元素。
  </template>
  
  <script>
    class NameTag extends Polymer.Element {
      static get is() { return "name-tag"; }
      
      // 设置该元素的 owner 属物
      constructor() {
        super();
        this.owner = "Daniel";
      }
    }
    
    customElements.define(NameTag.is, NameTag);
  </script>
</dom-module>

index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://polygit.org/components/webcomponentsjs/webcomponents-loader.js"></script>
    <link rel="import" href="name-tag.html">
  </head>
  <body>
    <name-tag></name-tag>
  </body>
</html>

Plunker 上尝试:

  • 尝试编辑owner 属物的值。
  • 尝试添加另一个属物并将其绑定到组件中。  提示:将 this.propertyName = "Property contents"; 添加到构造函数中 并将 {{propertyName}} 添加到元素的阴影DOM。

了解更多:数据绑定

属物是元素的公共 API 的重要组成部分。Polymer 声明的属物 支持许多常见的用于属物的模式——设置默认值,从标记配置属物,观察属物更改,以及更多。

以下示例声明来自于上一个示例的 owner 属物。 它还展示了在 index.html 中用标记配置 owner 属物。

configurable-name-tag.html
<link rel="import"  href="https://polygit.org/components/polymer/polymer-element.html">

<dom-module id="configurable-name-tag">

  <template>
    <!-- 绑定到 "owner" 属物 -->
    这是 <b>[[owner]]</b> 的 name-tag 元素。
  </template>
  
  <script>
    class ConfigurableNameTag extends Polymer.Element {
      static get is() { return "configurable-name-tag"; }
      // 配置 owner 属物
      static get properties() {
        return {
          owner: {
            type: String,
            value: "Daniel",
          }
        };
      }
    }
    customElements.define(ConfigurableNameTag.is, ConfigurableNameTag);
  </script>

</dom-module>

index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://polygit.org/components/webcomponentsjs/webcomponents-loader.js"></script>
    <link rel="import" href="configurable-name-tag.html">
  </head>
  <body>
    <!-- 通过设置相应的属性值来从标记配置属物 -->
    <configurable-name-tag owner="Scott"></configurable-name-tag>
  </body>
</html>

Try it out in Plunker:

  • Try editing the initial value of owner in index.html. Observe how this sets the property directly from your HTML.

了解更多:声明的属物

除文本内容之外,您还可以绑定到元素的 属物 (使用 property-name="[[binding]]")。Polymer 属物可以选择性地支持双向绑定, 使用花括号 (property-name="{{binding}}")。

的值绑定到元素的 (iron-input) 的值绑定到元素的 owner 属物,因此它将在用户输入时进行更新。

editable-name-tag.html
<link rel="import"  href="https://polygit.org/components/polymer/polymer-element.html">
<!-- 导入 iron-input 元素 -->
<link rel="import"  href="https://polygit.org/components/iron-input/iron-input.html">

<dom-module id="editable-name-tag">

  <template>
    <!-- 绑定到 "owner" 属物 -->
    <p>这是 <b>[[owner]]</b> 的 name-tag 元素。</p>
    
    <!-- iron-input 暴露一个可双向绑定的输入框值 -->
    <iron-input bind-value="{{owner}}">
      <input is="iron-input" placeholder="这里填您的名字...">
    </iron-input>
  </template>

  <script>
    class EditableNameTag extends Polymer.Element {
      static get is() { return "editable-name-tag"; }
      
      // 配置 owner 属物
      static get properties() {
        return {
          owner: {
            type: String,
            value: 'Daniel'
          }
        };
      }
      
    }
    customElements.define(EditableNameTag.is, EditableNameTag);
  </script>

</dom-module>

index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://polygit.org/components/webcomponentsjs/webcomponents-loader.js"></script>
    <link rel="import" href="editable-name-tag.html">
  </head>
  <body>
    <editable-name-tag></editable-name-tag>
  </body>
</html>

Plunker 上尝试:

  • 编辑输入框内容以观察双向数据绑定如何工作的。

注意: <iron-input> 元素包装了原生的 <input> 元素,并提供双向数据绑定和输入校验。

模板重复器 (dom-repeat) 是一个绑定到数组的专用模板。它为数组中的每个项创建模板内容的一个实例。

employee-list.html
<!-- 导入 polymer-element -->
<link rel="import"  href="https://polygit.org/components/polymer/polymer-element.html">

<!-- 导入模板重复器 --> 
<link rel="import"  href="https://polygit.org/components/polymer/lib/elements/dom-repeat.html">

<dom-module id="employee-list">
  <template>
    <div> 雇员列表:</div>
    <p></p>
    <template is="dom-repeat" items="{{employees}}">
        <div>First name: <span>{{item.first}}</span></div>
        <div>Last name: <span>{{item.last}}</span></div>
        <p></p>
    </template>
  </template>
  <script>
    class EmployeeList extends Polymer.Element {
      static get is() { return "employee-list"; }
      
      // 设置元素的雇员属物
      constructor() {
        super();
        this.employees = [
          {first: 'Bob', last: 'Li'},
          {first: 'Ayesha', last: 'Johnson'},
          {first: 'Fatma', last: 'Kumari'},
          {first: 'Tony', last: 'Mori'}
        ]; 
      }
    }
  customElements.define(EmployeeList.is, EmployeeList);
  </script>

</dom-module>

index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://polygit.org/components/webcomponentsjs/webcomponents-loader.js"></script>
    <link rel="import" href="employee-list.html">
  </head>
  <body>
    <employee-list></employee-list>
  </body>
</html>

Plunker 上尝试:

  • 更改 this.employees 中的名字和姓氏
  • 在 Tony Morelli 之后,通过将以下文本插入数组定义添加另一名员工:
       {first: 'Shawna', last: 'Williams'} 
    

Don't forget to make sure your commas are correct!

了解更多:模板重复器

现在您已经了解了这些基本的 Polymer 概念,您可以 使用 App 工具箱创建 App 或查看 Polymer 库的功能概述