2014-10-07 110 views
3

在下面的代碼中,當我嘗試以編程方式訪問它或在Chrome中檢查DOM時,模板#欄的內容「Foo」始終爲空。有人能解釋爲什麼嗎?帶模板內容的聚合物自定義元素

一般而言,如何將外部元素中定義的模板提供給內部元素,以便內部元素可以訪問內容並有條件地克隆或導入內容?

我正在使用聚合物0.4.2。

<polymer-element name="x-inner" noscript> 
    <!-- 
     How can I access the content "Foo" of <template>Foo</template>, 
     So that I can import/clone it here? 

     Using <content> moves the template from x-outer to x-inner, 
     but the template's .content property is empty, instead of 'Foo' as I expected. 
    --> 
    <content></content> 
</polymer-element> 

<polymer-element name="x-outer" noscript> 
    <template> 
     <x-inner> 
      <!-- 
       How can I pass a template to a custom element? 
       I don't want the contents of this template to be rendered 
       here in x-outer, but instead conditionally rendered by x-inner 
      --> 
      <template id="bar">Foo</template> 
     </x-inner> 
    </template> 
</polymer-element> 

<x-outer></x-outer> 

回答

1

此主題可能很複雜,下面是一些可幫助您入門的內容。

(這是對這個答案的第三次更新,確認上面關於'複雜'= P的那一點)。

聚合物包括TemplateBinding.js庫。

TemplateBinding.js庫提供了<template>,其中包含許多功能,包括與模型的數據綁定,條件戳記以及通過陣列的複製/迭代。它還增加了一個功能,克隆的嵌套模板不會複製它們自己的內容,從而防止在迭代時可能爆發無用節點。相反,TemplateBinding.js在克隆嵌套模板中創建原始內容模板的引用。結果是,如果您使用TemplateBinding.js,則應使用template.createInstance() API以獲得最佳結果。

現在,當使用沒有TemplateBinding.js的原始模板時,您可以簡單地使用var nodes = document.importNode(template.content, true)來標記模板。當然,在這種情況下,您不會獲得嵌套的模板複製優化(這可能會也可能不重要)。

注:

  1. 我刪除從<x-inner> 模板<content>節點,因爲它沒有任何意義。下面的代碼直接從light-dom中取出 模板,並將該實例標記爲 影子根。
  2. 聲明x-inner之前x-outer,因爲後者取決於前者。

示例代碼:

<x-outer></x-outer> 

<polymer-element name="x-inner"> 
<template> 
</template> 
<script> 

    Polymer({ 
    domReady: function() { 
     this.renderTemplate(); 
    }, 
    renderTemplate: function() { 

     // note: this only works if `template` is a true child of `this` 
     // (as opposed to projected) 
     var template = this.querySelector('template'); 

     // use createInstance from TemplateBinding.js library API 
     this.shadowRoot.appendChild(template.createInstance()); 

     /* 
     // this would work for raw templates, but Polymer includes TemplateBinding.js 
     this.shadowRoot.appendChild(stampTemplate(template)); 
     */ 

     /* 
     // if you don't know whether TemplateBinding.js exists or not, 
     // you could do something like this (see stampTemplate definition below) 
     this.shadowRoot.appendChild(stampTemplate(template)); 
     */ 

     /* 
     // this way uses the binding feature of TemplateBinding.js 
     template.setAttribute('bind', ''); 
     template.model = { /* some data */ }; 
     */ 
    } 
    }); 

    // use best available API 
    function stampTemplate(template) { 
    if (template.createInstance) { 
     return template.createInstance(); 
    } else { 
     return document.importNode(template.content, true); 
    } 
    } 

</script> 
</polymer-element> 

<polymer-element name="x-outer" noscript> 
<template> 

    <x-inner> 
    <template id="bar">Foo</template> 
    </x-inner> 

</template> 
</polymer-element> 

http://jsbin.com/nemaha/14/edit

+0

感謝您的詳細的解答,特別是示出了在聚合物基本的HTML模板和模板之間的差異。我想我會仔細看看TemplateBinding.js的內部 – 2014-10-09 23:57:21

相關問題