Object.observe()可以与Polymer一起使用吗?

时间:2015-08-04 21:16:55

标签: polymer polymer-1.0

在我的理想世界中,我希望Polymer组件能够透明地使用Object.observe()来监听模型属性的更改,没有模型对象不得不自己是自定义元素。

在下面的示例中,我的元素具有model类型的属性Object。 HTML模板使用{{model.name}},我希望该属性在该属性更改时自动更新。

在我的演示/示例中,我实现此目标的方法是在自定义代码中使用Object.observe(),当发生任何更改时,我将model设置为undefined然后再返回。这会“刷新”UI并获取更改。当然,在任何不平凡的用户界面中,这都会非常笨拙,所以这有点像“希望不是战略”的时刻......

现在是否有任何简洁的设计模式和/或将来做这些事情的路线图?

这是我的自定义元素:

<link rel="import" href="../bower_components/polymer/polymer.html">
<dom-module id="test-view">
  <template>
    <p>Hello, I am called <span>{{model.name}}</span>, how are you?</p>
  </template>
</dom-module>

<script>
  Polymer({
    is: 'test-view',
    properties: {
      model: Object,
    },
    observers: [
      '_modelChanged(model)'
    ],
    ready: function() { },
    attached: function() { },
    detached: function() { },
    _modelChanged: function(model) {
      if (model) { Object.observe(model, this._observer.bind(this)); }
    },
    _observer: function() {
      const oldModel = this.model;
      this.model = undefined;
      this.model = oldModel;
    }
  });
</script>

这是一个HTML页面,通过其状态转换驱动它:

<html>
  <head>
    <script src="../bower_components/webcomponentsjs/webcomponents.js"></script>
    <link rel="import" href="../test-view/test-view.html">
  </head>
  <body>
    <test-view id="first" model='{ "name": "Wilma" }'></test-view>
    <script>
      const newModel = { name: 'Fred' };
      const testView = document.querySelector('#first');
      window.setTimeout(function() { testView.model = newModel; }, 2000);
      window.setTimeout(function() { newModel.name = 'Barney'; }, 4000);
    </script>
  </body>
</html>

1 个答案:

答案 0 :(得分:0)

这可能不是你问题的完整答案,更多是评论,但由于代码在评论中看起来不太好,我仍然将其作为答案发布。我认为,如果没有额外的观察者,这种事情甚至可以在0.5中发挥作用。但是,为了提高性能,这种行为在1.0中被删除了。我也希望我们能在某个时候收回它。

为避免将模型设置为undefined而返回触发刷新,您也可以只通知Polymer更改。我认为这会更有效,特别是当你有复杂的对象和大量的数据绑定时。

_observer: function(changes) {
    changes.forEach(function(change){
        this.notifyPath("model." +change.name, change.object[change.name]);
    }.bind(this));
}