具有模板内容的聚合物自定义元素

时间:2014-10-07 01:50:56

标签: polymer

在下面的代码中,当我尝试以编程方式或在Chrome中检查DOM时,模板#bar的内容“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 个答案:

答案 0 :(得分:1)

这个主题可能很复杂,下面是让你入门的事情。

(这是这个答案的第三次更新,确认了上面关于'复杂'= P的位。)

Polymer包含TemplateBinding.js库。

TemplateBinding.js库赋予<template>许多功能,包括数据绑定模型,条件标记和通过数组复制/迭代。它还添加了一个功能,克隆的嵌套模板不会复制自己的内容,从而防止迭代时可能爆炸的无用节点。相反,TemplateBinding.js会在克隆嵌套模板中创建对原始内容模板的引用。结果是,如果您使用TemplateBinding.js,则应使用template.createInstance() API以获得最佳效果。

现在,在使用不带TemplateBinding.js的原始模板时,您只需使用var nodes = document.importNode(template.content, true)标记模板即可。当然,在这种情况下,您不会获得嵌套模板复制优化(可能或可能不重要)。

注意:

  1. 我从<content>移除了<x-inner>节点  模板,因为它没有用处。下面的代码摘下了  模板直接从light-dom中取出,并将实例标记为  阴影根。
  2. x-inner之前声明x-outer,因为后者取决于前者。
  3. 示例代码:

    <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