10202


お世話になっています。  
現在BootstrapとPolymerを使用してWebサイト制作をしています。

さっそく質問なのですが、Polymerを使用して定義した独自コンポーネントに外部で  
用意したScriptファイルを  
![画像の説明をここに入力](https://i.stack.imgur.com/SHGl5.png)  
と読み込み、コンポーネント内の要素にScriptを適用したいのですが、どうやら  
現在適用されていないようです。  
試した方法としては  
・polymer-elementタグの外側でScript読み込みを定義  
・templateタグの中でScript読み込みを定義  
したのですが、反映されていないようです。

どなたかScriptを反映する方法をご存知の方はいらっしゃいませんでしょうか？  
Polymerのverは0.5.5  
Bootstrapのverは3.3.4です。


CC BY-SA 3.0
2015-05-14T15:40:18.963
10190
2015-05-15T00:55:23.743
297
question
bootstrap polymer
Polymerでの外部Scriptファイルの読み込み方法について


動作しないコードが掲載されていないので、推測になります。

# 原因

[前回の質問](https://ja.stackoverflow.com/questions/9736/polymer%E3%81%A8bootstrap%E3%81%AE%E4%BD%B5%E7%94%A8%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/9787)と同じく、ShadowDOM
の仕様による現象だと考えられます。

前回 私は ShadowDOM の外側で定義された **CSS ルールが適用されない** と記述しましたが、より厳密には **CSS
セレクタがマッチしない** と言うべきだったでしょう。CSS セレクタがマッチしない結果、ルールが適用されません。

さて、CSS セレクタを利用する場面は、CSS ルール定義だけではありません。  
JavaScript から DOM 要素を検索する場合にも利用されます。

[code]

    $('#myModal').modal('show')
    
[/code]

> ※ <http://getbootstrap.com/javascript/> より抜粋

例えば、この`#myModal`は、`myModal`という`id`属性を持つ DOM 要素にマッチする CSS セレクタです。

ここで、分かりやすくするために検索部分を生の DOM API で書き直してみます。

[code]

    var myModal = document.querySelector('#myModal');
    $(myModal).modal('show');
    
[/code]

`document.querySelector`はグローバル (つまり、ShadowDOM の外側) で CSS
セレクタを用いて検索を行います。`<script>`タグが ShadowDOM の中に書かれていても、`document`オブジェクトは ShadowDOM
の外側です。

そして CSS セレクタは ShadowDOM 境界を超えないので、`document.querySelector('#myModal')`では
ShadowDOM の中にある`#myModel`要素にはヒットしません。  
例えば、次のような状況で

[code]

    <thirdparty-library-button>ライブラリのボタン</thirdparty-library-button>
    <div>てきすと</div>
    <script>
      var div = document.querySelector('div');
    </script>
    
[/code]

`<thirdparty-library-button>`要素の中から div 要素を取ってこられたら困る、というのが理由です。ShadowDOM
境界のお陰で`<thirdparty-library-
button>`要素の中がどのように書かれているか意識する必要がなく、その内部実装が変化してもアプリケーションには影響しにくくなります。

# 解決方法

ShadowDOM の内部を検索するためには、ShadowDOM のルート ノードとなる ShadowRoot
オブジェクトの`querySelector`メソッドを利用します。

[code]

    Polymer({
      ready: function() {
        var myModal = this.shadowRoot.querySelector('#myModal');
        $(myModal).hoge(); // ready コールバックで .show() したら酷いので慌てて変更
      }
    });
    
[/code]

もしくは、[Polymer が用意してくれる`$`プロパティ](https://www.polymer-
project.org/0.5/docs/polymer/polymer.html#automatic-node-finding)を利用します。

[code]

    Polymer({
      ready: function() {
        $(this.$.myModal).hoge(); // ready コールバックで .show() したら酷いので慌てて変更
      }
    });
    
[/code]

なお、ライブラリの`<script>`は1度だけ読み込むべきなので、本体の HTML 側で読み込むか、専用の HTML ファイルを作って import
しましょう。

[code]

    // lib/bootstrap.html
    <script src="bootstrap.js"></script>
    
    // your-component.html
    <link rel="import" href="lib/bootstrap.html">
    <polymer-element name="your-component">
    ...
    </polymer-element>
    
[/code]

こうすることで、複数のコンポーネントから import した場合でも、読み込まれるのは1度だけになります。

WebComponents を利用すると設計が大きく変わるので、WebComponents を想定していないライブラリとの併用は大変ですね。


CC BY-SA 3.0
2015-05-15T00:55:23.743
10202
2015-05-15T00:55:23.743
2017-04-13T12:52:38.920
-1
4809
10190
answer