Google polymerの所感

# Google polymerの所感

## はじめに

<font color="red">**再利用可能なUIコンポーネント**</font>を作りたいなと思い、以下のキーワードをベースに調べていました。

・template
・shadow dom
・Web Components
・サポートブラウザ
・データバインディング

何を気にしていたかと言うと、フロントエンドを複数人(ないしは、複数会社)で開発していて、よくある困ったことは

1. CSSのclass/idが被る
2. styleがぶつかる -> ぶっ壊れる -> importantが出てき始める。。
3. jsも同様
4. なんかもう、煩雑。書きっぷりがバラバラ -> 誰もいじりたくなくなる。修正が至難の技になる

とかでしょうか。。。気づかないうちに神みたいなjsが出来上がってたとか。

## それで、どうすればいいのだろう??

そこで目をつけたのが、WebComponents。これに関しては、多くの方が丁寧に解説なさっているので、[こちら](https://blog.agektmr.com/2014/05/web-components.html?m=1)等、見ていただければと思います。

ようはwebcomponent使って、カスタム化したタグだけをチームに使わせて、UIコンポーネントを作成する人は「独立して再利用可能なパーツを作成 -> チームに提供する」って形にすれば良いのでは???ということがしたいのです。

## 課題

なんですけど、課題があります。
webcomponentの大切な概念でもあるshadow domがchromeでしか使えなかったり、とにかくまだまだブラウザによってサポート範囲がまちまちです。
[can i use](http://caniuse.com/#search=shadow%20dom)とか見ていただくと、状況がわかるかと思います。

## そこでpolymer

polyfillってのが以下です。

```
古いブラウザーに欠けている部分、新しいブラウザーでも足りない機能の穴を埋めること
```

webcomponentをサポートしていないブラウザは、既存技術(jsとか)で埋め合わせて、使えるように振舞わせようって話です。
ここからは、とっとと使って行ってみます。
なお。今回はGoogleのpolyfill、<font color="red">**polymer**</font>を使います。
![alt](https://www.polymer-project.org/images/logos/lockup.svg)

## 導入

詳しくは[公式](https://www.polymer-project.org/1.0/)を見ていただきたいのですが、
今回はbowerを使います。
適当なローカル作業フォルダ下で

```
bower init
bower bower install --save Polymer/polymer
bower update
```

すると、bower.jsonが今になり、

``` bower.json
    1	{
     2	  "name": "recycle_components",
     3	  "authors": [
     4	    "yueguchi"
     5	  ],
     6	  "description": "this is recycle_components by google polymer.",
     7	  "main": "",
     8	  "moduleType": [],
     9	  "license": "MIT",
    10	  "homepage": "",
    11	  "ignore": [
    12	    "**/.*",
    13	    "node_modules",
    14	    "bower_components",
    15	    "test",
    16	    "tests"
    17	  ],
    18	  "dependencies": {
    19	    "polymer": "Polymer/polymer#^1.4.0",
    20	  }
    21	}

```

bower_components下にpolymerとwebcomponentsjsが作成されます。
これで導入は完了です。

## 使ってみる
### index.html
以下の挙動をpolymerを使って試します。

- 自作カスタムタグ
- データバインディング
- cssのscope化

ドキュメントルート下に

``` index.html
<!DOCTYPE html>
<html>
  <head>
    <script src="bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
    <link rel="import" href="proto-import-element.html">
  </head>
  <body>
    <main-document-element hoge="fuga"></main-document-element>
  </body>
</html>
```

を作成します。これはUIコンポーネントを使う側です。

```
<main-document-element hoge="fuga"></main-document-element>
```

ここが今回やりたかった<font color="red">**再利用可能なUIコンポーネントをカスタムタグを指定するだけで実現する**</font>になります。

### UIコンポーネント作成

``` proto-import-element.html
<link rel="import" href="bower_components/polymer/polymer.html">
<link rel="import" href="bower_components/iron-input/iron-input.html">
<dom-module id="main-document-element">
    <template>
        <div class="eg-my-input-div">
            <p>
                <b>{{hoge}}</b>Hi! I'm a Polymer element that was defined in the main document!
            </p>
            <input is="iron-input" bind-value="{{hoge}}" placeholder="Your name here...">
        </div>
    </template>
    <style>
        .eg-my-input-div {
            background-color: blue;
        }

    </style>
    <script>
        HTMLImports.whenReady(function() {
            Polymer({
                is: 'main-document-element',
                properties: {
                    hoge: {
                        type: String,
                        value: "hoge"
                    }
                },
                ready: function() {
                }
            });
        });
    </script>
</dom-module>
```

作成したら、画面で見ましょう。
以下のようなUIに、入力フォームに入力した値がバインディングされて文字列が動的に変化するかと思います。
IE、FF、chrome,safariで確認できました。

![スクリーンショット 2016-04-24 0.05.13.png](https://qiita-image-store.s3.amazonaws.com/0/78857/20774099-7967-271c-fdb0-46bfc48831c2.png)

流れとしては、以下です。

1. Polymer関数を使う
2. Polymer関数のisにカスタム要素名を指定する
3. カスタム要素の中身をtemplate内に記述する
4. dom-module id="main-document-element"でPolymer関数のisと紐付ける
5. 必要に応じてstyleやjsを書く
6. 使い手(index.html)で、使いたいカスタム要素を持つhtmlファイルをimportする
↓以下。
```
<link rel="import" href="proto-import-element.html">
```

importすることで、proto-import-element.html内で作成したカスタム要素である
<main-document-element>が使えます。

```
<main-document-element hoge="fuga"></main-document-element>
```

また、地味にキャプチャに開発者ツールでのinspectorを載せたのですが、
今回カスタム要素に当てたstyleである、

```
.eg-my-input-div {
   background-color: blue;
}
```

は、ソースコードを見る限り、html全体で「class="eg-my-input-div"」にstyleが当たってしまうのでは?と思いますが、
inspectorをよく見ると、

```
class="eg-my-input-div style-scope main-document-element"
```

elementは↑となっており、
styleは

```
.eg-my-input-div.main-document-element {
    background-color: blue;
}
```

と鳴ってます。つまり、main-document-elementカスタム要素の中のclassがeg-my-input-divにだけ適用されるstyleと言えます。

### 追記・補足

データバインディングを実現するにあたり、「**iron-input**」を使用しました。
欲しい機能は、Polymerがカタログという形で提供してくれています。
https://elements.polymer-project.org/browse

今回はここから、データバインディングinputを使いました。

使いたい時は、bowerに以下を指定し、更新するだけです。

```
bower install --save PolymerElements/iron-input
bower update
```

これでbower_componets下にiron系のモジュールができているはずです。

今回は以上です。もう少し使ってみて、有用性なり、レポートできればと思います。

## 感想・所感

今のトコ、やりたかったことが一通り実現できているので期待してます。
まだ表面さらった程度の知識なので、もう少し検証して、使い手はタグを指定するだけで欲しいUIが実現できるUIコンポーネントを作成できるか試してみます。

カオスな開発は終わらせたいですよね!!