仕事でPolymerを使うことになりました。
まずは、どこがwebcomponentsで、どこがPolymerがやってくれてることなのかを把握するためにwebcomponentsで書いた場合とPolymerで書いた場合のコードを比較したいと思います。
Quick tour of PolymerをWebComponentsで書いてみて比較します。
Register an element
まずはwebcomponents.
動作確認
<!DOCTYPE html>
<script>
var ProtoElement = Object.create(HTMLElement.prototype);
ProtoElement.createdCallback = function () {
this.textContent = "I'm a proto-element. Check out my prototype!"
};
document.registerElement('proto-element', {
prototype: ProtoElement
});
</script>
次にPolymer
<!DOCTYPE html>
<link rel="import"
href="http://www.polymer-project.org/1.0/samples/components/polymer/polymer.html">
<script>
// register a new element called proto-element
Polymer({
is: "proto-element",
// add a callback to the element's prototype
ready: function() {
this.textContent = "I'm a proto-element. Check out my prototype!"
}
});
</script>
まだメリットを感じない。
Add local DOM
webcomponents
動作確認
<!DOCTYPE html>
<template id="dom-element">
<p>I'm a DOM element.This is a Shadow DOM!</p>
</template>
<script>
var DomElement = Object.create(HTMLElement.prototype);
var doc = this.document.currentScript.ownerDocument;
DomElement.createdCallback = function () {
var shadowRoot = this.createShadowRoot();
var template = doc.querySelector('#dom-element');
var clone = document.importNode(template.content, true);
shadowRoot.appendChild(clone);
};
document.registerElement('dom-element', {
prototype: DomElement
});
</script>
Polymer
<!DOCTYPE html>
<link rel="import"
href="http://www.polymer-project.org/1.0/samples/components/polymer/polymer.html">
<dom-module id="dom-element">
<template>
<p>I'm a DOM element. This is my local DOM!</p>
</template>
<script>
Polymer({
is: "dom-element"
});
</script>
</dom-module>
Shadow Domを使おうとすると途端にPolymerが簡単になります。
Compose with local DOM
webcomponents
動作確認
picture-frame.html
<!DOCTYPE html>
<template id="picture-frame">
<!-- scoped CSS for this element -->
<style>
div {
display: inline-block;
background-color: #ccc;
border-radius: 8px;
padding: 4px;
}
</style>
<div>
<!-- any children are rendered here -->
<content></content>
</div>
</template>
<script>
var DomElement = Object.create(HTMLElement.prototype);
var doc = this.document.currentScript.ownerDocument;
DomElement.createdCallback = function () {
var shadowRoot = this.createShadowRoot();
var template = doc.querySelector('#picture-frame');
var clone = document.importNode(template.content, true);
shadowRoot.appendChild(clone);
};
document.registerElement('picture-frame', {
prototype: DomElement
});
</script>
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<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>
Polymer
picture-frame.html
<link rel="import"
href="http://www.polymer-project.org/1.0/samples/components/polymer/polymer.html">
<dom-module id="picture-frame">
<!-- scoped CSS for this element -->
<style>
div {
display: inline-block;
background-color: #ccc;
border-radius: 8px;
padding: 4px;
}
</style>
<template>
<div>
<!-- any children are rendered here -->
<content></content>
</div>
</template>
<script>
Polymer({
is: "picture-frame",
});
</script>
</dom-module>
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<script src="http://www.polymer-project.org/1.0/samples/components/webcomponentsjs/webcomponents-lite.min.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>
<content>
タグを使ってもさほど変わらない。結局、Shadow Domの部分が楽になる
Use data binding
data bindingはwebcomponetsにはないのでPolymer偉いです。
例えば双方向バインディングはこんな感じです。
<link rel="import"
href="http://www.polymer-project.org/1.0/samples/components/polymer/polymer.html">
<!-- import the iron-input custom element -->
<link rel="import"
href="http://www.polymer-project.org/1.0/samples/components/iron-input/iron-input.html">
<dom-module id="editable-name-tag">
<template>
<p>
This is a <strong>{{owner}}</strong>'s editable-name-tag.
</p>
<!-- iron-input exposes a two-way bindable input value -->
<input is="iron-input" bind-value="{{owner}}"
placeholder="Your name here...">
</template>
<script>
Polymer({
is: "editable-name-tag",
properties: {
owner: {
type: String,
value: "Daniel"
}
}
});
</script>
</dom-module>