dom-repeat中的项目更改未传达给其他项目

时间:2017-08-16 14:54:15

标签: javascript html polymer

我们正在构建聚合物应用程序。 我们有元素数组,它们使用 dom-repeat 显示在组件中。以下是一个示例代码段:

//main component
<h2>List of elements</h2>
<template is="dom-repeat" items="{{elements}}" as="item" indexAs="index">
    <another-component element="{{item}}" ident$="{{index}}"></another-component>
</template>

//sub component
<h3>{{element.name}}</h3>
<h4>{{element.person.name}}</h4>
<paper-button on-tap="_changeName">Change name!</paper-button>

数组的对象有一些共同的引用。你可以这样看:

//main component
<script>
    var fred = {"name": "fred"};
    var tom = {"name": "tom"};

    Polymer({
        is: 'example-component',
        properties: {
            elements: {
                type: Array,
                value: [{"name": "Main1", "person": fred}, {"name": "Main2", "person": tom}, {"name": "Main3", "person": fred}],
                notify: true
            }
        }
    });
</script> 

现在,在我的项目中,我希望能够更改嵌套元素。

在此示例中,我希望项目3的人员值发生变化。

但由于第3项的人员参考与第1项相同,我也希望第1人改变。

但是,我所经历的是第1项未更新。

There is a complete example setup at this address.(我可以让jsfiddle正确使用我的依赖项......)。

到目前为止,我试图研究

  • 听众
  • notifyPath
  • 观察员

没有成功。 我也想避免将我的整个数组传递给我的项目。

我知道使用像Redux这样的状态对象很容易解决,所以不幸的是,这不是解决方案。

我在互联网上找到了很多关于如何让数据泡沫化的资源,但不是像我现在想做的那样冒泡。

任何帮助都将不胜感激。

完整的参考代码:

主要组件

<link rel="import" href="/polymer/polymer.html">
<link rel="import" href="/components/another-component/another-component.html">

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

        <h1>Example</h1>

        <h2>List of elements</h2>
        <template is="dom-repeat" items="{{elements}}" as="item" indexAs="index">
            <another-component element="{{item}}" ident$="{{index}}"></another-component>
        </template>

    </template>
    <script>
        var fred = {"name": "fred"};
        var tom = {"name": "tom"};

        Polymer({
            is: 'example-component',
            properties: {
                elements: {
                    type: Array,
                    value: [{"name": "Main1", "person": fred}, {"name": "Main2", "person": tom}, {"name": "Main3", "person": fred}],
                    notify: true
                }
            }
        });
    </script>
</dom-module>

子组件

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

        <h3>{{element.name}}</h3>
        <h4>{{element.person.name}}</h4>
        <paper-button on-tap="_changeName">Change name!</paper-button>

    </template>
    <script>
        Polymer({
            is: 'another-component',
            properties: {
                element: {
                    type: Object,
                    notify: true
                }
            },

            _changeName: function(){
                this.set('element.person', {"name": "bobby"});
                this.notifyPath('elements');
                this.notifyPath('element');
                this.notifyPath('element.person');

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

谢谢,

2 个答案:

答案 0 :(得分:1)

您可能希望让实际执行更改的元素触发一个事件,说明它更改了值。然后让父元素监听它,当它收到更改的事件时,它可以执行this.notifyPath('elements');调用。

在对notifyPath的调用中,您传入的是对象,但它应该是字符串路径而不是对象。

答案 1 :(得分:1)

子组件不会更改父组件的值。正如雅各布迈尔斯所建议的,你需要发射一个事件来改变价值。然后从父元素中监听,您可以在其中通知整个元素数组的更改。

以下是plnkr链接:http://plnkr.co/edit/tuqKh4ANUTspa05GZ9mi?p=preview

子组件即another-component正在触发事件&#39;更改名称&#39;:

this.fire('change-name', {"newPersonName" : "bobby","index":this.i });

父组件即example-component正在侦听该事件并通知更改:

this.addEventListener('change-name', function (e) {
     this.elements[e.detail.index].person.name = e.detail.newPersonName;

     for(var i =0; i< this.elements.length; i++){
             this.notifyPath('elements.'+i+'.person.name'); 
     }

 });

要通知我们需要使用更改的确切路径,因此我将notifyPath保持在循环中(我没有找到其他方法)。我希望这会有所帮助。