Polymer 1.x:Obervers 错误?修复或解决方法?

Polymer 1.x: Obervers bug? Fix or Workaround?

首先让我说,我 90% 确定这是 Polymer 观察者系统的错误。

进行以下测试并注意以下意外行为:

测试程序

  1. Open this JSBin.
  2. 切换 <paper-toggle-button>
  3. 请注意 changes 变量 没有 像预期的那样递增。
  4. <paper-input> 字段中输入任何文本。
  5. 注意 changes 变量 确实 按预期增加。
  6. 再次切换 <paper-toggle-button>
  7. 请注意 changes 变量 现在 按预期递增。

请注意,我也观察到 <paper-dropdown-menu> 存在与 <paper-toggle-button> 相同的问题,但为简洁起见,在此问题中省略了它。

问题

  • What's going on here?
  • Is this a bug?
  • Is there any workaround or fix?
http://jsbin.com/saxewimowu/edit?html,输出
<html>
<head>
  <title>My Element</title>
  <script data-require="polymer@*" data-semver="1.0.0" src="http://www.polymer-project.org/1.0/samples/components/webcomponentsjs/webcomponents-lite.js"></script>
  <script data-require="polymer@*" data-semver="1.0.0" src="http://www.polymer-project.org/1.0/samples/components/polymer/polymer.html"></script>
  <base href="http://element-party.xyz/" />
  <link rel="import" href="all-elements.html" />
</head>
<body>
  <dom-module id="my-element">
    <template>
      <paper-input value="{{str::input}}"></paper-input><br />
      <paper-toggle-button checked="{{bool}}"></paper-toggle-button><br />
      <br />changes:<span>[[num]]</span><br />      
      <br />str: <span>[[str]]</span><br />
      <br />bool:<span>[[bool]]</span><br />
    </template>
    <script>
      (function() {
        Polymer({
          is: 'my-element',
          observers: [
            'inputChanged(str, bool)'
          ],
          inputChanged(a, b) {
            if(! this.num){
              this.set('num', 1);
            } else {
              this.set('num', (this.num + 1) );
            }
          }
        });
      })();
    </script>
  </dom-module>
  <my-element></my-element>
</body>
</html>

它在两个属性的值都不同 undefined(我猜是 null)之后执行。 输入文本并单击切换按钮后,每次更改都会打印 A。 要变通为您的属性分配默认值。

我加了

      properties: {
        str: {
          type: String,
          value: ''
        },
        bool: {
          type: Boolean,
          value: false
        }            
      },

根据您的要求,我无法再重现您的问题。

解决方法是单独观察道具。

 (function() {
    Polymer({
      is: 'my-element',
      properties: {
        str:        {
          type:       String,
          notify:     true,
          observer:   '_somethingChanged'
        },
        bool:       {
          type:       Boolean,
          notify:     true,
          observer:   '_somethingChanged'
        }
      },
      _somethingChanged: function(evt) {
        // At this point, evt contains infos about what changed. Eg path and value.
        console.log('Something changed');
      },
    });
  })();

另一种解决方法是使 strbool 成为同一 属性 的一部分(名为 foo 的对象)并观察 foo.*

  (function() {
    Polymer({
      is: 'my-element',
      properties: {
        foo:        {
          type:       Object,
          notify:     true,
          value:      function(){
            return {
              str:     'Default',
              bool:    false
            }
          }
        },
      },
      observers: [ '_somethingChanged(foo.*)' ],
      _somethingChanged: function() {
        // At this point, evt contains infos about what changed. Eg path and value.
        console.log('Something changed');
      },
    });
  })();

为了完整起见,我将添加源代码和this link to the JSBin of the accepted answer and working solution

http://jsbin.com/pufalegofe/1/edit?html,输出
<html>
<head>
  <title>My Element</title>
  <script data-require="polymer@*" data-semver="1.0.0" src="http://www.polymer-project.org/1.0/samples/components/webcomponentsjs/webcomponents-lite.js"></script>
  <script data-require="polymer@*" data-semver="1.0.0" src="http://www.polymer-project.org/1.0/samples/components/polymer/polymer.html"></script>
  <base href="http://element-party.xyz/" />
  <link rel="import" href="all-elements.html" />
</head>
<body>
  <dom-module id="my-element">
    <template>
      <paper-input value="{{str::input}}"></paper-input><br />
      <paper-toggle-button checked="{{bool}}"></paper-toggle-button><br />
      <br />changes:<span>[[num]]</span><br />      
      <br />str: <span>[[str]]</span><br />
      <br />bool:<span>[[bool]]</span><br />
    </template>
    <script>
      (function() {
        Polymer({
          is: 'my-element',
          properties: {
            str: {
              type: String,
              value: ''
            },
            bool: {
              type: Boolean,
              value: false
            }            
          },
          observers: [
            'inputChanged(str, bool)'
          ],
          inputChanged: function(a, b) {
            if(! this.num){
              this.set('num', 1);
            } else {
              this.set('num', (this.num + 1) );
            }
          }
        });
      })();
    </script>
  </dom-module>
  <my-element></my-element>
</body>
</html>