FizzBuzz
PolymerでFizzBuzzを表示するタグ(コンポーネント、カスタム要素)を作成し、その定義の仕方や ループ(繰り返し)、条件分岐(if文) の方法を確認します。
※ Polymer サンプルコード (1) Hello, World ! の続きです。
- 動作確認
- Windows 10 : ○ Chrome60, Firefox54, Edge40 × IE11
- Mac 10.3 : ○ Chrome60, Safari10.1
- Android 7.1 : ○ Chrome60
画面イメージ
サンプルコード
-
index.htmlFizzBuzzタグの呼出し元
<script src="https://polygit.org/components/webcomponentsjs/webcomponents-loader.js"></script>
<link rel="import" href="fizz-buzz.html">
<fizz-buzz max="20"></fizz-buzz>
-
fizz-buzz.htmlFizzBuzzを表示するHTML
<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">
<link rel="import" href="https://polygit.org/components/polymer/lib/elements/dom-if.html">
<dom-module id="fizz-buzz">
<template strip-whitespace>
<template is="dom-repeat" items="[[_nums]]">
<div>
<template is="dom-if" if="[[_isFizz(item)]]">Fizz</template>
<template is="dom-if" if="[[_isBuzz(item)]]">Buzz</template>
<template is="dom-if" if="[[_isNum(item)]]">[[item]]</template>
</div>
</template>
</template>
<script>
class FizzBuzz extends Polymer.Element {
static get is() { return 'fizz-buzz' }
static get properties() {
return {
max: {
type: Number,
value: 10
},
_nums: {
type: Array,
computed: "_initNums(max)"
}
}
}
_initNums(max) {
// generate numbers array [1...max]
return Array.from(new Array(max)).map((v, i) => return i + 1)
}
_isFizz(num) {
return num % 3 == 0
}
_isBuzz(num) {
return num % 5 == 0
}
_isNum(num) {
return num % 3 != 0 && num % 5 != 0
}
}
customElements.define(FizzBuzz.is, FizzBuzz)
</script>
</dom-module>
各行の説明
index.html
<script src="https://polygit.org/components/webcomponentsjs/webcomponents-loader.js"></script>
Web Componentsのポリフィルを読み込みます。
<link rel="import" href="fizz-buzz.html">
<fizz-buzz>タグを読み込みます。
<fizz-buzz max="20"></fizz-buzz>
<fizz-buzz>タグを表示し、max属性で数えあげる最大値を指定します。
fizz-buzz.html
<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">
<link rel="import" href="https://polygit.org/components/polymer/lib/elements/dom-if.html">
Polymerでタグ(コンポーネント、カスタム要素)を定義するにはpolymer/polymer-element.htmlを読み込みます。ここで<dom-module>という定義用のタグが使えるようになります。
バージョン1.xとの互換モードではpolymer/polymer.html(-elementなし)を指定し、こちらは一括で<dom-*>系のタグを読み込んでくれましたが、2.x系では繰り返し処理のdom-repat、条件分岐のdom-ifはそれぞれ別個で読み込む必要があります。
<dom-module id="fizz-buzz">
<template strip-whitespace>
...
</template>
<script>
class FizzBuzz extends Polymer.Element {
static get is() { return 'fizz-buzz' }
...
}
customElements.define(FizzBuzz.is, FizzBuzz)
</script>
</dom-module>
<fizz-buzz>タグを定義します。<dom-module id="foo-bar">とcustomElements.define()に渡す名前(foo-bar)を一致させる必要があります。作成できるタグには間に-(ハイフン)を入れなければいけない等のルールがあり、<fizzbuzz>とか<-FIZZ-BUZZ->とかは作れません。(<fizz-buzz/>のような終了タグがないものも作れません)
<template>にstrip-whitespaceを指定すると生成するHTMLから余計な空白を除去してくれるそうです(参考: Polymer templateのstrip-whitespaceについて)。
古いブラウザ向けにはES5に変換するか、1.x系の互換モードでファクトリメソッドを使用して定義します(まだ主要なライブラリでもこちらの書き方をしているのが多いです)。
<link rel="import" href="https://polygit.org/components/polymer/polymer.html"> <dom-module id="fizz-buzz"> <template> ... </template> <script> Polymer({ is: 'fizz-buzz', ... }) </script> </dom-module>
<template is="dom-repeat" items="[[_nums]]">
<div>
...
</div>
</template>
繰り返し処理には<dom-repeat>タグを使用しますが、<dom-module>のテンプレート内であれば省略記法の<template is="dom-repeat">を使います。items属性にArray等の配列を指定すると繰り返し処理がされ、デフォルトでitemという名前の変数に値がセットされます。
突然itemという変数が出現するのに違和感があれば、as="num"を指定するとnum変数に値がセットされ、_isFizz(num)と書くことができます)。
他にfor文とかwhile文とかありません。繰り返しはdom-repeat一択です。
直接i=0; i<=10 ; i++のような値でループ回数の指定はできずArrayを渡す必要がありますが、filter="..."、sort="..."などで制御でき、initial-count="10"で最初にレンダリングする個数を10に指定することなどができます。
<template is="dom-if" if="[[_isFizz(item)]]">Fizz</template>
<template is="dom-if" if="[[_isBuzz(item)]]">Buzz</template>
<template is="dom-if" if="[[_isNum(item)]]">[[item]]</template>
_isFizz(num) {
return num % 3 == 0
}
_isBuzz(num) {
return num % 5 == 0
}
_isNum(num) {
return num % 3 != 0 && num % 5 != 0
}
こちらも条件分岐の<dom-if>タグは省略記法で<template if="dom-if">と書きます。
他にif-else文とかswitch文はありません。条件分岐もdom-if一択です。
githubのリポジトリには基本のタグが置かれているので、Pull Requestを送ると増やしてくれるのかもしれません。
[[_isFizz(item)]]はclass FizzBuzzで宣言しているメソッド_isFizz(num)を呼び出し、表示の為の真偽判定をしています。
static get properties() {
return {
max: {
type: Number,
value: 10
},
_nums: {
type: Array,
computed: "_initNums(max)"
}
}
}
_initNums(max) {
...
}
<fizz-buzz>タグにおいて属性(attribute)を定義するには、properties()メソッドでプロパティを定義します。
max: 数値型の初期値で10の属性を定義します。
_nums:computedで指定している関数_initNums(max)はmaxプロバティの値が変更される度に呼び出され、その結果の配列が_numsにセットされます。
ちなみにメソッド定義部分の _initNums(max) { ... }のmaxは関数の引数名で、computed: "_initNums(max)"が指すのはFizzBuzzクラスのmaxプロパティです。メソッド内からFizzBuzzクラスのmaxプロパティを参照するにはthis.maxを使用します。
最後に
コメント、編集リクエスト歓迎
Polymer サンプルコード (3) SPA へ続きます。
以上
