我希望有一个带有两个子元素的聚合物元素,一个子元素生成数据,另一个子元素在数据更改时执行某些操作(在我的情况下:向服务器发送通知)。

为了实现这一点,我编写了一个聚合物元素,即root,它具有以下结构(为了简化讨论而更改了名称):

<producer data={{foo.bar}}></producer>
<consumer data=[[foo]]></consumer>


生产者使用set('property', 'value')方法更改数据,以便root元素可以看到通知。问题在于consumer元素不会注意到对foo的更改,因为它们涉及子属性。

为了解决这个问题,我尝试使用computed binding如下:

<producer data={{foo.bar}}></producer>
<consumer data=[[_compute(foo)]]></consumer>

...
_compute: function() {
    return this.foo;
}


但是,这不会导致consumer收到通知。我认为这是因为返回的对象是相同的引用(仅更改了子属性)。当前,我使用的解决方法是使用以下版本的compute函数:

_compute: function() {
    return Object.assign({}, this.foo);
}


这行得通(consumer元素得到通知),但是我认为这可能不是最有效的(我在每次_compute调用时都创建一个对象)和/或优雅的方式。然后我的问题是:在Polymer中实现此行为的正确方法是什么?

最佳答案

您有权修改使用者元素吗?

解决此问题的最佳方法是让使用者元素具有多属性观察器,该观察器侦听data属性上的子属性更改。

它可能看起来像这样:

Polymer({
    is: 'consumer',
    properties: {
        data: Object
    },
    observers: ['consumeData(data, data.*)'],
    consumeData: function (data) {
        //Do whatever you were planning on doing with data here
    }
});


这样的方法的优势在于,您的“消费者”元素只是“知道”当子对象的属性更改时如何使用该数据对象。由于Polymer中数据绑定的方法比较轻巧,因此尝试在“消费者”元素之外实现此行为将必然更加昂贵且更加复杂,因为这需要通过诱使数据绑定使数据对象成为新对象,它带有对副本的新引用,或者完全放弃了数据绑定,并在事件之上构建了一种方法,并在使用者身上响应事件来调用方法。因此,如果可能的话,我建议您尝试上述方法。

Polymer的数据绑定与其他一些双向启用的数据绑定实现的工作方式不同,例如您在AngularJS中可能会发现的那样。而不是使用非常昂贵的脏检查,Polymer使用基于事件的“路径通知”方法。当属性的子属性更改时,具有该属性的Polymer元素将向绑定到该属性的直接子对象触发一个事件,通知他们路径'property.subProperty'已更改。为了使消费者能够对这些更改采取行动,必须告知消费者沿着“ property.subProperty”路径进行更改。我们使用上述语法在聚合物观察器中指定路径。在这种情况下,将data。*放在观察者中意味着我们要侦听数据的任何路径,以便data属性上任何已通知的属性更改都将触发观察者。

09-11 19:02
查看更多