在 Polymer 中重置表单 2.x
Resetting forms in Polymer 2.x
我正在尝试重置我的表格。我究竟做错了什么?什么是最佳实践?
我在演示中遇到的问题是 connectedCallback()
似乎持续触发(不仅仅是在初始加载时),因此通过将 savedItem
更新为 newItem
来丢失 savedItem
的值更新。
Here is the same issue on Github.
https://plnkr.co/edit/wRdXXws2UXl3VXrycqua?p=preview
我的-demo.html
<base href="https://polygit.org/polymer+v2.0.0/shadycss+webcomponents+1.0.0/components/">
<link rel="import" href="polymer/polymer-element.html">
<link rel="import" href="paper-toggle-button/paper-toggle-button.html">
<dom-module id="my-demo">
<template>
<style>
:host > * {
margin-top: 40px;
font-size: 18px;
}
button.save {
color: white;
background-color: blue;
}
</style>
<paper-toggle-button checked="{{item.alice}}">Alice</paper-toggle-button>
<paper-toggle-button checked="{{item.bob}}">Bob</paper-toggle-button>
<paper-toggle-button checked="{{item.charlie}}">Charlie</paper-toggle-button>
<paper-toggle-button checked="{{item.dave}}">Dave</paper-toggle-button>
<button>Reset</button>
<button class="save" on-tap="_reset">Save</button>
</template>
<script>
class MyDemo extends Polymer.Element {
static get is() {
return 'my-demo';
}
static get properties() {
return {
item: {
type: Object,
notify: true,
value: () => {
return {
alice: false,
bob: false,
charlie: false,
dave: true,
};
},
},
savedItem: {
type: Object,
notify: true,
},
};
}
connectedCallback() {
super.connectedCallback();
this.set('savedItem', this.item);
}
static get observers() {
return [
'_itemChanged(item.*)',
];
}
_itemChanged(newItem) {
console.log('saved-item', this.savedItem);
console.log('new-item', newItem);
}
_reset() {
this.set('item', this.savedItem);
}
}
window.customElements.define(MyDemo.is, MyDemo);
</script>
</dom-module>
编辑
重现问题的步骤
打开控制台。
在 Plunker 中导航到我的-demo.html
单击其中一个切换开关。
控制台通知,savedItem
属性更新为当前item
属性.
注意,这似乎是以下代码块的结果。
connectedCallback() {
super.connectedCallback();
this.set('savedItem', this.item);
}
但这怎么可能呢?因为我认为 connectedCallback()
只在初始化时触发一次?
tldr; 在这种情况下,connectedCallback()
实际上并没有被多次调用。 savedItem
和 item
在您的代码中始终是同一个对象,因为 JavaScript 传递对象 by reference.
对象引用
在下面:
connectedCallback() {
this.set('savedItem', this.item);
}
_reset() {
this.set('item', this.savedItem);
}
savedItem
和 item
都是对同一对象的引用。调用 this.set()
不会自动克隆操作数(=
运算符也不会)。
一个解决方案是在赋值前克隆对象(使用ES2017 object-spread operator):
connectedCallback() {
this.savedItem = {...this.item};
}
_reset() {
this.item = {...this.savedItem};
}
最佳实践(或更简单的重置方法)
重置表单的更简单方法是让 iron-form
处理表单的 reset
事件,它将表单的命名输入重置为其初始值。这使您不必声明 savedItem
并且不需要额外的 JavaScript 来管理它。
为此,将 <paper-toggle-button>
包装在 <iron-form>
中,并向其添加 name
属性。然后,在表单中插入一个<input type="reset">
,作为重置按钮。
<iron-form>
<form>
<paper-toggle-button name="alice" checked="{{item.alice}}">Alice</paper-toggle-button>
<paper-toggle-button name="bob" checked="{{item.bob}}">Bob</paper-toggle-button>
<paper-toggle-button name="charlie" checked="{{item.charlie}}">Charlie</paper-toggle-button>
<paper-toggle-button name="dave" checked="{{item.dave}}">Dave</paper-toggle-button>
<input type="reset" class="save">
</form>
</iron-form>
我正在尝试重置我的表格。我究竟做错了什么?什么是最佳实践?
我在演示中遇到的问题是 connectedCallback()
似乎持续触发(不仅仅是在初始加载时),因此通过将 savedItem
更新为 newItem
来丢失 savedItem
的值更新。
Here is the same issue on Github.
https://plnkr.co/edit/wRdXXws2UXl3VXrycqua?p=preview
我的-demo.html<base href="https://polygit.org/polymer+v2.0.0/shadycss+webcomponents+1.0.0/components/">
<link rel="import" href="polymer/polymer-element.html">
<link rel="import" href="paper-toggle-button/paper-toggle-button.html">
<dom-module id="my-demo">
<template>
<style>
:host > * {
margin-top: 40px;
font-size: 18px;
}
button.save {
color: white;
background-color: blue;
}
</style>
<paper-toggle-button checked="{{item.alice}}">Alice</paper-toggle-button>
<paper-toggle-button checked="{{item.bob}}">Bob</paper-toggle-button>
<paper-toggle-button checked="{{item.charlie}}">Charlie</paper-toggle-button>
<paper-toggle-button checked="{{item.dave}}">Dave</paper-toggle-button>
<button>Reset</button>
<button class="save" on-tap="_reset">Save</button>
</template>
<script>
class MyDemo extends Polymer.Element {
static get is() {
return 'my-demo';
}
static get properties() {
return {
item: {
type: Object,
notify: true,
value: () => {
return {
alice: false,
bob: false,
charlie: false,
dave: true,
};
},
},
savedItem: {
type: Object,
notify: true,
},
};
}
connectedCallback() {
super.connectedCallback();
this.set('savedItem', this.item);
}
static get observers() {
return [
'_itemChanged(item.*)',
];
}
_itemChanged(newItem) {
console.log('saved-item', this.savedItem);
console.log('new-item', newItem);
}
_reset() {
this.set('item', this.savedItem);
}
}
window.customElements.define(MyDemo.is, MyDemo);
</script>
</dom-module>
编辑
重现问题的步骤
打开控制台。
在 Plunker 中导航到我的-demo.html
单击其中一个切换开关。
控制台通知,
savedItem
属性更新为当前item
属性.注意,这似乎是以下代码块的结果。
connectedCallback() { super.connectedCallback(); this.set('savedItem', this.item); }
但这怎么可能呢?因为我认为 connectedCallback()
只在初始化时触发一次?
tldr; 在这种情况下,connectedCallback()
实际上并没有被多次调用。 savedItem
和 item
在您的代码中始终是同一个对象,因为 JavaScript 传递对象 by reference.
对象引用
在下面:
connectedCallback() {
this.set('savedItem', this.item);
}
_reset() {
this.set('item', this.savedItem);
}
savedItem
和 item
都是对同一对象的引用。调用 this.set()
不会自动克隆操作数(=
运算符也不会)。
一个解决方案是在赋值前克隆对象(使用ES2017 object-spread operator):
connectedCallback() {
this.savedItem = {...this.item};
}
_reset() {
this.item = {...this.savedItem};
}
最佳实践(或更简单的重置方法)
重置表单的更简单方法是让 iron-form
处理表单的 reset
事件,它将表单的命名输入重置为其初始值。这使您不必声明 savedItem
并且不需要额外的 JavaScript 来管理它。
为此,将 <paper-toggle-button>
包装在 <iron-form>
中,并向其添加 name
属性。然后,在表单中插入一个<input type="reset">
,作为重置按钮。
<iron-form>
<form>
<paper-toggle-button name="alice" checked="{{item.alice}}">Alice</paper-toggle-button>
<paper-toggle-button name="bob" checked="{{item.bob}}">Bob</paper-toggle-button>
<paper-toggle-button name="charlie" checked="{{item.charlie}}">Charlie</paper-toggle-button>
<paper-toggle-button name="dave" checked="{{item.dave}}">Dave</paper-toggle-button>
<input type="reset" class="save">
</form>
</iron-form>