【问题标题】:How to dynamically add elements in a template in polymer如何在聚合物的模板中动态添加元素
【发布时间】:2016-01-12 15:53:25
【问题描述】:

我有一个 dom-repeat 模板(Polymer 1.2.3)并希望它根据模型渲染元素。

根据item 中的值,模板应该呈现一个按钮或一个复选框或其他事先不知道的东西。这是我尝试过的:

<template is="dom-repeat" items=[[myItems]]>
    <div>[[_render(item)]]</div>
</template>

_render 函数在此处返回一个 DOM 元素,但这不起作用(如预期的那样)。

_render: function() {
    return document.createElement('paper-button');
}

如果在调用_render 函数时模板会添加对它要添加的DOM 元素的引用,这对这种事情会有什么用处。然后我可以用它来按需添加孩子。

【问题讨论】:

标签: javascript polymer


【解决方案1】:

我也尝试过,但似乎没有将元素作为要在 dom-repeat 中呈现的项目传递。 根据问题的复杂程度和要渲染的内容,我只能想到两种解决方案。

1) 这里到处都是 dom-if 元素,看起来很乱

<script>
Polymer({
  is: 'your-element',
  properties: {
    myItems: {
      type: Array,
      value: [
        { type: 'checkbox', other: 'something', },
        { type: 'button', other: 'something else', },
      ]
    },
  },
  isCheckbox: item => item.type === 'checkbox',
  isButton: item => item.type === 'button',
});
</script>

<template is="dom-repeat" items="[[myItems]]">
  <div>
    <template id="dom-if" if="{{isCheckbox(item)}}">
      <input type="checkbox" other="{{item.other}}" />
    </template>
    <template id="dom-if" if="{{isButton(item)}}"">
      <paper-button other="{{item.other}}" ></paper-button>
    </template>
  </div>
</template>

2) 这会在你的外部和内部 dom 之间留下一个烦人的自定义重复元素,并且会使得访问呈现的元素变得更加困难

<dom-module id="custom-repeat">
  <template>
  </template>
</dom-module>

<custom-repeat array="{{anArrayOfElementProperties}}"></custom-repeat>

<script>
HTMLImports.whenReady(function () {
  Polymer({
    is: 'custom-repeat',
    properties: {
      items: {
        type: Array,

        // a default value just for an example
        value: [
          {name: 'paper-fab', icon: 'add' },
          {name: 'iron-icon', icon: 'star' },
          {name: 'paper-fab', icon: 'alarm' },
          {name: 'iron-icon', icon: 'apps' },
        ],
        observer: 'itemsChanged',
      },
    },
    itemsChanged: function(items) {
      // Delete all children
      // Add new children based on items
    },
  });
});
</script>

示例 2 显示为here

我不太喜欢这两个答案,但希望它能让你渡过难关,直到有人找到一种方法来改变 dom-repeat 元素的呈现方式以允许传递实际节点,或者了解何时传递对 dom-的引用节点。

【讨论】:

    【解决方案2】:

    我尝试使用记录在 here 的 Polymer DOM-API 来挂钩 dom-repeat 模板的呈现操作。使用这种方法你只需要做这样的事情。

     Polymer.dom(this.$.domrep).observeNodes(function(info) {
         var nList = info.addedNodes.filter(function(node) {
             return (node.nodeType === Node.ELEMENT_NODE && node.tagName === 'DIV')
         });
    
        this.processNewNodes(nList);
     }) 
    

    processNewNodes 函数中,您可以将元素附加到由 dom-repeat 模板呈现的节点上。然而,由于不同的原因,这不是一个好的解决方案。例如它不能与iron-list 中使用的模板一起使用。可能会发生节点被添加但节点的模型在模板实例中尚不可用的情况。这意味着您不能根据模型将子节点附加到列表项。

    这是我最终使用的解决方案,我很满意:

    我为列表项创建了第二个 dom 模块,我将其用作 dom-repeatiron-list 元素内的节点。您可以将 DOM 元素作为属性传递给此列表项元素。

    <link rel="import" href="../../bower_components/polymer/polymer.html">
    
    <dom-module id="list-item">
        <template></template>
    </dom-module>
    <script>
    Polymer({
        is: 'list-item',
    
        properties: {
            renderObject: {
                type: Object,
                observer: '_render'
            }
        },
    
        _render: function(newV) {
            if (!newV) return true;
            var root = Polymer.dom(this.root);
    
            // remove previously rendered nodes
            while (root.firstChild) {
                root.removeChild(root.firstChild)
            }
    
            root.appendChild(newV);
    
        }
    });
    </script>
    

    每当您更改模型时,列表项都会删除并重新创建渲染节点。如果您不想在每次模型更改时删除并重新创建项目,那么您应该能够将第二个属性 itemValue 添加到列表项。然后,您可以观察itemValue 的变化,并根据需要对现有的 DOM 元素进行调整。

    这种方法将模板器的操作与模板项的呈现操作分开。所以预计不会有干扰。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-11
      相关资源
      最近更新 更多