3

我正在尝试在 Polymer 3 Web 组件中理解/实现两种方式的属性绑定。我有以下代码:

import {html, PolymerElement} from '@polymer/polymer/polymer-element.js';

 class CustomInputComponent extends PolymerElement {
    static get template() {
        return html`        
        <div>
            <template is="dom-repeat" items="{{ratings}}">
                <input type="radio" 
                       name="group" 
                       id="item_{{item.id}}" 
                       value="{{item.checked}}" 
                       checked$="{{item.checked}}">                
            </template>
        </div>`;
    }

    static get properties() {
        return {
            ratings: {
                type: Array,
                value: [
                    { id: 1, checked: true },
                    { id: 2, checked: false }
                ]
            }
        };
    }
}
window.customElements.define('custom-input-component', CustomInputComponent);

如您所见,我定义了一个包含默认值列表的 Array 属性。这个属性是一个模型,我想从中渲染一个无线电组。初始状态看起来不错。但是当我单击未选中的输入时,DOM 元素不会正确更新。

尽管我单击了第二个元素,但浏览器也显示了第一个元素。

我敢打赌我错过了一些非常简单的东西......

4

1 回答 1

4

主要的事情是:

  • 您正在绑定到checked属性 ( $=),但是我认为无线电输入不会动态更新其checked属性。AFAICT,该checked 属性是选择输入时发生的变化。

  • 此外,本机<input type="radio">输入只会在它们被选中时触发它们的changeinput事件,而不是在它们被取消选中时触发。Polymer 依靠事件来触发数据绑定等属性效果;这意味着向上的数据绑定(从输入到您的自定义元素)只会checked在输入上的属性从 更改为false时得到处理true。实际上,一旦ratings[n].checked成为真的,它就永远不会成为假的,因为 Polymer 无法知道这已经发生了。

    顺便说一句,要对原生 HTML 元素执行双向绑定,您还需要为单选输入在选择时触发的事件添加注释。因此,如果您确实想捕获选择时的更改,则类似于checked="{{item.checked::change}}".

几个选项:

  • 在 a中使用paper-radio-buttonspaper-radio-group而不是原生<input>s。这些元素对于双向数据绑定表现良好。

  • 检查新项目时侦听更改,并手动更新ratings[n].checkedfalse先前选择的项目。

关于您的代码的更多信息

  • (我认为这与您当前的问题无关,但它有助于避免将来出现问题)在为 Polymer 元素中的对象或数组属性初始化默认值时,请记住使用一个函数,以便每个元素实例获得自己独特的数组或对象。例如:

    ratings: { type: Array, value: function(){ return [ { id: 1, checked: true }, { id: 2, checked: false } ]; } }

  • 通常我认为,您不想更改无线电输入的。按照惯例,当<form>提交包含单选输入组时,value当前单选输入上的checked将包含在表单数据中,而其他单选输入值将被忽略。这是 W3Schools 上的一个示例。所以,而不是value="{{item.checked}}",类似的东西value="[[item.data]]"

所以整个事情可能是这样的

class CustomInputComponent extends PolymerElement {
  static get properties () {
    return {
      ratings: {
        type: Array,
        value: function(){ 
          return [
          { id: 1, checked: true, value: 'pie' },
          { id: 2, checked: false, value: 'fries' },
          { id: 3, checked: false, value: 'los dos' }
          ];
        }
      },
      selected: {
        // type: Number or Object, idk
        // Keep track of the selected <input>
      }
    };
  }
  static get template() {
    return html`        
      <p>do you want pie or fries?</p>
      <div id="mydiv">
        <template is="dom-repeat" items="{{ratings}}">
          <input 
            type="radio"
            name="testgroup"
            id="[[item.id]]"
            value="[[item.value]]"
            checked="{{item.checked::input}}"
            on-change="radioChanged"
            >[[item.value]]
          </input>
        </template>
      </div>
    `;
  }
  radioChanged(event){
    // update ratings[n].checked for selected input
    // set selected input to currently selected input
  }
}
于 2018-06-16T19:14:02.697 回答