Polymer对象的属性不会触发setInterval方法

时间:2017-02-21 21:42:15

标签: javascript data-binding polymer setinterval

我有一个<paper-progress>栏,我想用它来显示时间的流逝。要更新条形图的值,我使用名为setInterval的循环方法来更新dom-module的属性。当我记录属性的值时,我看到正在正确添加值,但不幸的是我的进度条没有移动。就好像属性的更改没有被条形属性上的数据绑定集捕获。下面是一个大大减少的代码来举例说明它。

<dom-module id="x-test">
    <template>
        <paper-progress
          value="{{progresso.value}}"
          min="{{progresso.min}}"
          max="{{progresso.max}}"
          class="transiting">
        </paper-progress>
    </template>
    <script>
    Polymer({
      is: 'x-test',
      properties: {
        progresso: {
            type: Object,
            value: {
                min: 0,
                max: 10000,
                value: 0
            }
        }
      },
      attached: function(){
        var timer = setInterval(this.count,1000);
      },
      count: function(){
        var progresso = document.querySelector('test').progresso;
        try {
          if (progresso.value < progresso.max) {
            progresso.value = progresso.value + 100;
          } else {
            progresso.value = progresso.max;
          }
        } catch (e) {
          console.log(e.name + ": " + e.message);
        }
      }
    });
    </script>
</dom-module>

我错过了什么?为了让<paper-progress>元素看到progresso dom-module属性中的更改,我该怎么办?两个元素都在同一个模块中。

P.S。:

  • 我从上面的代码段中省略了clearInterval();但它包含在代码中。
  • 我不知道它是否会产生任何影响,但实际的Javascript代码在我添加到聚合物对象的行为中。

编辑:我在复制和粘贴代码时犯了一些错误。我修改了上面的代码以反映真实的代码。还添加了一些评论,以使我的情况更加清晰。

1 个答案:

答案 0 :(得分:4)

通知子属性更新

当您拥有data binding to a subproperty时,设置子属性直接赢得不会自动更新数据绑定。您必须手动拨打this.notifyPath(SUBPROPERTY_PATH)

this.progresso.value = 20;
this.notifyPath('progresso.value');

...或使用this.set(SUBPROPERTY_PATH, VALUE)

this.set('progresso.value', 20);

元素命名

您好像正在尝试定义名为test的自定义元素,但是Web组件规范requires the element name be hyphenated,因此名称应该类似于x-test

<dom-module id="x-test">
  <template>...</template>
  <script>
    Polymer({
      is: 'x-test',
      ...
    });
  </script>
</dom-module>

声明聚合物方法

要在Polymer对象上声明方法,请指定所需的方法名称,后跟冒号,然后指定函数表达式:

Polynmer({
  // this.count: function() {  // DON'T DO THIS
  count: function() {
    ...
  }
});

查询DOM

请注意document.querySelector()查询整个文档而不是Polymer元素。查询文档可能会有问题,因为您可能在文档中有多个元素实例(如果您在特定元素之后需要将类或ID应用于元素以供选择),并且document.querySelector()不能查询元素的影子DOM。

从Polymer方法中,您应该使用this.$$(SELECTOR)(或Polymer.dom(this.root).querySelector(SELECTOR)),它适用于Shady DOM(在Polymer 1中默认)或Shadow DOM(在Polymer 2中默认)。

var myEl = this.$$('a-class-in-my-element');

注意:事实证明您根本不需要查询元素(请参阅访问元素属性)。

访问元素属性

由于progresso是您的Polymer对象的属性,您可以从Polymer方法直接从this(例如this.progresso)访问它,因此count()应该看起来像这样:

count: function() {
  // var progresso = document.querySelector('test').progresso;   // DON'T DO THIS
  var progresso = this.progresso;
  ...
}

初始化Object属性

要初始化Object属性的值,请务必use a function that returns the intial value。否则,元素的所有实例将共享相同的Object,这可能会导致无意的副作用。

Polymer({
  ...
  properties: {
    progresso: {
      type: Object,
      value: function() {
        return {min: 0, max: 10000, value: 0};
      }
    }
  }
});

绑定回调上下文

请注意,您需要绑定setInterval回调的上下文,以便它引用您的Polymer对象(以便您的回调&#39; this引用Polymer对象而不是外部对象context,通常是Window对象。)

attached: function() {
  setInterval(this.count.bind(this), 1000);
}

清理分离

假设你可以分离你的元素,你应该在detached中添加清理来停止在attached中启动的间隔计时器:

attached: function() {
  this._timerId = setInterval(...);
},
detached: function() {
  clearInterval(this._timerId);
}

&#13;
&#13;
HTMLImports.whenReady(() => {
  Polymer({
    is: 'x-test',
    properties: {
      progresso: {
        type: Object,
        value: () => ({
          min: 0,
          max: 10000,
          value: 0
        })
      }
    },
    attached: function() {
      this._timerId = setInterval(this.count.bind(this), 1000);
    },
    detached: function() {
      clearInterval(this._timerId);
    },
    count: function() {
      const progresso = this.progresso;
      if (progresso.value < progresso.max) {
        this.set('progresso.value', progresso.value + 100);
        console.log('value', progresso.value);
      } else {
        this.set('progresso.value', progresso.max);
        clearInterval(this._timerId);
      }
    }
  });
});
&#13;
<head>
  <base href="https://polygit.org/polymer+1.9.3/components/">
  <script src="webcomponentsjs/webcomponents-lite.js"></script>
  <link rel="import" href="polymer/polymer.html">
  <link rel="import" href="paper-progress/paper-progress.html">
</head>
<body>
  <x-test></x-test>

  <dom-module id="x-test">
    <template>
      <style>
        paper-progress {
          --paper-progress-height: 20px;
          width: 100%;
        }
      </style>
      <paper-progress
          value="{{progresso.value}}"
          min="{{progresso.min}}"
          max="{{progresso.max}}"
          class="transiting">
       </paper-progress>
    </template>
  </dom-module>
</body>
&#13;
&#13;
&#13;

codepen