聚合物 – 重复轻dom元素

在我的组件中,我想重复一个项目列表,其中包含由组件的光dom提供的模板.例如:

<template is="dom-repeat" items="{{items}}">
    <content select="#itemTemplate"></content>
</template>

但是,似乎Polymer只插入轻量级元素#itemTemplate一次而不是多次.有没有其他方法来重复轻dom元素?

最佳答案 我创建了一个简单的原型,它允许您指定轻型DOM模板的重复次数.

因为内容在轻量级DOM中,所以您可以像往常一样从外部设置样式.并且模板内部的数据绑定也有效,因为我已经从Templatizer实现了_forwardParentProp和_forwardParentPath方法.

请注意,我没有实现特定于实例的属性,这将允许每行特定的变量,例如index和item.当然,这可以完成,但需要更多的工作.

查看原型:JSBin.

好的,我们来详细说明:

test元素的使用以及对两个输入元素的数据绑定非常简单:

<template is="dom-bind">
    Number of repeats: <input type="text" value="{{repeats::input}}" /> <br />
    Custom message: <input type="text" value="{{customMessage::input}}" />

    <test-element repeats="{{repeats}}">
        <template>
            <h1>Title!</h1>

            <p>
                Custom message: <em>[[customMessage]]</em>
            </p>
        </template>
    </test-element>
</template>

注意dom-bind,它是创建数据绑定范围所必需的.

至于test-element,整个源代码如下所示:

<dom-module id="test-element">
    <template>
      <style>
        :host {
          display: block;
        }
      </style>

          <content></content>
    </template>

    <script>
        Polymer({

            is: 'test-element',

            behaviors: [
                Polymer.Templatizer,
            ],

            properties: {
                repeats: {
                    type: Number,
                    value: 3,
                    notify: true,
                },
            },

            observers: [
                '_repeatsChanged(repeats)',
            ],

            _repeatsChanged: function(repeats) {
                // First time only: initialize template
                if (this.template === undefined) {
                    this.template = Polymer.dom(this).querySelector('template');
                    this.templatize(this.template);
                }

                // Remove previously stamped children
                while (Polymer.dom(this).firstChild) {
                    Polymer.dom(this).removeChild(Polymer.dom(this).firstChild);
                }

                // Stamp new ones
                this.stamped = new Array(repeats);

                var inst;
                for (var i = 0; i < repeats; i++) {
                    inst = this.stamp(null);
                    this.stamped[i] = inst.root.querySelector('*');
                    Polymer.dom(this).appendChild(inst.root);
                }
            },

            // Copied from iron-list
            _forwardParentProp: function(prop, value) {
                if (this.stamped) {
                    this.stamped.forEach(function(item) {
                        item._templateInstance[prop] = value;
                    }, this);
                }
            },

            // Copied from iron-list
            _forwardParentPath: function(path, value) {
                if (this.stamped) {
                    this.stamped.forEach(function(item) {
                        item._templateInstance.notifyPath(path, value, true);
                    }, this);
                }
            },

        });
    </script>
</dom-module>

只有一个属性,重复,指定标记实例的数量.默认值为3.为了适应所述属性值的更改,已创建观察者.这也是冲压发生的地方:

_repeatsChanged: function(repeats) {
    // First time only: initialize template
    if (this.template === undefined) {
        this.template = Polymer.dom(this).querySelector('template');
        this.templatize(this.template);
    }

    // Remove previously stamped children
    while (Polymer.dom(this).firstChild) {
        Polymer.dom(this).removeChild(Polymer.dom(this).firstChild);
    }

    // Stamp new ones
    this.stamped = new Array(repeats);

    var inst;
    for (var i = 0; i < repeats; i++) {
        inst = this.stamp(null);
        this.stamped[i] = inst.root.querySelector('*');
        Polymer.dom(this).appendChild(inst.root);
    }
},

>首先(并且只有一次),从轻量级DOM读取模板
调用模板化方法.这个方法初始化了
模板化行为.
>其次,所有以前盖章的孩子都被移除(这样的话
元素不仅无限积累).
>第三,根据目前的价值,新生儿被加盖印章
重复.所有标记的实例都保存到this.stamped中
从外部到工作的数据绑定需要.

最后但并非最不重要的是,Templatizer行为是通过两种方法实现的(两种方法未实现):

// Copied from iron-list
_forwardParentProp: function(prop, value) {
        if (this.stamped) {
                this.stamped.forEach(function(item) {
                        item._templateInstance[prop] = value;
                }, this);
        }
},

// Copied from iron-list
_forwardParentPath: function(path, value) {
        if (this.stamped) {
                this.stamped.forEach(function(item) {
                        item._templateInstance.notifyPath(path, value, true);
                }, this);
        }
},

这两种方法都取自铁清单.他们遍历标记的子项并传播属性更改和路径通知.

点赞