我有以下函数,以便更新四个不同输入字段的值:
已更新
我的包类定义如下:
class Package {
constructor(packageID, type, weight, height, description) {
this.packageID = packageID;
this.type = type;
this.weight = weight;
this.height = height;
this.description = description;
}
getPackageId() {
return this.packageId;
}
getType() {
return this.type;
}
getWeight() {
return this.weight;
}
getHeight() {
return this.height;
}
getDescription() {
return this.description;
}/*
setPackageId(packageId){
this.packageId= packageId
return packageId;
}*/
setType(type) {
this.type = type;
return type;
}
setWeight(weight) {
this.weight = weight;
return this.weight;
}
setHeight(height) {
this.height = height;
return this.height;
}
setDescription(description) {
this.description = description;
return this.description;
}
}
let inputfieldtype = document.getElementById('selectPackageType');
let inputfieldweight = document.getElementById('floatWeight');
let inputfieldheight = document.getElementById('floatHeight');
let inputfielddescription = document.getElementById('description');
function updateValues() {
var value = this.value;
if (value == null) {
console.log('value of packege is null');
} else if (value != "" && (inputfieldtype == 'selectPackageType')) {
type = value;
} else if (value != "" && (inputfieldweight == 'floatWeight')) {
weight = value;
} else if (value != "" && (inputfieldheight == 'floatHeight')) {
height = value;
} else if (value != "" && (inputfielddescription == 'description')) {
description = value;
}
}
inputfieldweight.addEventListener('change', updateValues);
inputfieldheight.addEventListener('change', updateValues);
inputfielddescription.addEventListener('change', updateValues);
inputfieldtype.addEventListener('change', updateValues);
到目前为止我了解到的是,我的 if 语句的条件没有用,因为在所有四种情况下,我想要与之比较的字符串都是 true。 我的目标如下:我想检查哪个输入字段已被单击,并且我想将该字段的值保存到变量中。
然后我想创建我的类“Package”的一个新实例,并用这个值填充它们的属性。
//Create instance of package
const package = new Package();
//shoot all the values into one package
function submit() {
if (typeof package != "undefined") {
package.packageID = randomID;
package.type = type;
package.weight = weight;
package.height = height;
package.description = description;
console.log(package);
} else {
console.log(package);
}
}
这是 HTML 代码
<form autocomplete="off">
<div class="custom-select">
<label for="selectPackageType">Type</label>
<select id="selectPackageType" name="type">
<option value="1">letter</option>
<option value="2">package</option>
</select>
</div>
</form>
<div class="fancy-input">
<label for="floatWeight">Weight</label>
<input id="floatWeight" name="floatWeight" maxlength="8">
</div>
<div class="fancy-input">
<label for="floatHeight">Height</label>
<input id="floatHeight" name="floatHeight" maxlength="8">
</div>
<div class="fancy-input">
<label for="description">Description</label>
<input id="description" name="description">
</div>
<button onclick="submit()">Submit</button>
我将代码更改为以下内容:
/**
* this class describes the package that should be send or collect
*/
class Package{
constructor(packageID, type, weight,height,description){
this.packageID = packageID;
this.type = type;
this.weight = weight;
this.height = height;
this.description= description;
}
getPackageId(){
return this.packageId;
}
getType(){
return this.type;
}
getWeight(){
return this.weight;
}
getHeight(){
return this.height;
}
getDescription(){
return this.description;
}
/*setPackageId(packageId){
this.packageId= packageId
return packageId;
}*/
setType(type){
this.type = type;
return type;
}
setWeight(weight){
this.weight = weight;
return this.weight;
}
setHeight(height){
this.height = height;
return this.height;
}
setDescription(description){
this.description = description;
return this.description;
}
}
//Generate PackageId
const generateID = () => Math.random().toString(36).slice(2);
//Global Variables
const randomID = generateID();
const formgetInputfields = document.getElementById("getInputfields");
const inputfieldtype = document.getElementById('selectPackageType');
const inputfieldweight = document.getElementById('floatWeight');
const inputfieldheight = document.getElementById('floatHeight');
const inputfielddescription = document.getElementById('description');
//Create instance of package
const package = new Package();
//shoot all the values into one package
function submit(){
const type = inputfieldtype.value;
const weight = inputfieldweight.value;
const height = inputfieldheight.value;
const description = inputfielddescription.value;
console.log(formgetInputfields);
if (typeof package != "undefined") {
package.packageID = randomID;
package.type = type;
package.weight = weight;
package.height = height;
package.description = description;
console.log(package);
}else {
console.log(package);
}
}
formgetInputfields.addEventListener("change", submit);
看起来有效。
为了易于维护/重构,解决方案应该实现通用且具有更高的抽象。
对于OP的用例,首先必须稍微重构表单标记,包括表单元素名称和
Package
类属性名称的统一。
说到后者,OP 的
Package
类实现引入了 getter 和 setter 方法,这些方法没有任何用途,因为 a) 无论如何,所有属性都是公共的,但 b) 也没有引入任何对 setter 实现的保护。获取/设置仅对受保护的数据有意义,因此是私有数据,人们可以控制如何允许访问甚至更改此类数据。 OP 最好使用最简单的 Package
抽象,仅包含公共数据。
包实例的创建应该始终与其形式相关。为了建立这样的关系,可以使用
WeakMap
实例,其中包配置表单元素作为其包实例的键,而后者必须根据任何表单元素进行更新其相关表单元素的值变化。
可以引入两个函数,
putPackageData
创建并注册表单相关的包实例,patchPackageData
从表单的当前元素值创建数据补丁并将其分配给表单相关的包 -实例。
人们必须利用例如...
WeakMap.prototype.set
WeakMap.prototype.get
FormData
构造函数
FormData.prototype.entries
Object.fromEntries
Object.assign
下一个提供的示例代码显示了刚刚描述的方法的可能实现,因为该方法是通用的,每次单个表单元素值更改或表单必须处理时,都会用所有当前可用的表单数据修补包提交事件。
function patchPackageData(evt) {
// - prevent the form from being submitted ...
// - but only in case a real event with its own `preventDefault` method was provided.
// - see ... [https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault]
// - see ... [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining]
evt.preventDefault?.();
const { currentTarget: formNode } = evt;
// - create a form-data instance.
// - see ... [https://developer.mozilla.org/en-US/docs/Web/API/FormData]
const formData = new FormData(formNode);
// - create an object from all form-data entries.
// - see ... [https://developer.mozilla.org/en-US/docs/Web/API/FormData/entries]
// - see ... [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/fromEntries]
const dataPatch = Object.fromEntries([...formData.entries()]);
// - get the form-element related package instance.
// - see ... [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap/get]
const package = packageRegistry.get(formNode);
// - assign the data-patch to the package instance.
// - see ... [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign]
Object.assign(package, dataPatch);
console.log('PATCH package data ...', package);
}
function putPackageData(formNode) {
// - create and register the form-element related package instance.
// - see ... [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap/set]
packageRegistry.set(
formNode, new Package({ id: formNode.dataset.packageId }),
);
console.log('PUT package data ...', packageRegistry.get(formNode));
// - assign more form-element related data to the newly created package instance.
patchPackageData({ currentTarget: formNode });
}
const packageRegistry = new WeakMap;
document
// - query every available package configuration related form element ...
.querySelectorAll('form[data-name="package-config"]')
// - ... where one for each form-element ...
.forEach(elmNode => {
// ... does trigger the creation and registration of the form-element related package instance.
putPackageData(elmNode);
// ... does register the correct handlers with the relevant event-types.
elmNode.addEventListener('change', patchPackageData);
elmNode.addEventListener('submit', patchPackageData);
});
body { margin: 0; }
form {
float: left;
width: 25%;
padding: 8px;
font-size: .8em;
label,
label > span {
display: block;
width: 100%;
}
label > span {
margin: 2px 0;
}
label, fieldset, [type="submit"] {
margin: 4px 0;
}
select, input {
width: 90%;
}
}
.as-console-wrapper {
left: auto!important;
bottom: 0;
width: 44%;
min-height: 100%;
}
<form data-name="package-config" data-package-id="6dfc38b8-41f0-4b4f-86d8-4aea355aef79" autocomplete="off">
<label>
<span>Type</span>
<select name ="type">
<option value="1">letter</option>
<option value="2">package</option>
</select>
</label>
<fieldset>
<legend>Measures</legend>
<label>
<span>Weight</span>
<input name="weight" maxlength="8" />
</label>
<label>
<span>Height</span>
<input name="height" maxlength ="8" />
</label>
</fieldset>
<label>
<span>Description</span>
<input name="description" />
</label>
<button type="submit">Submit</button>
</form>
<form data-name="package-config" autocomplete="off">
<label>
<span>Type</span>
<select name ="type">
<option value="1">letter</option>
<option value="2" selected>package</option>
</select>
</label>
<fieldset>
<legend>Measures</legend>
<label>
<span>Weight</span>
<input name="weight" maxlength="8" />
</label>
<label>
<span>Height</span>
<input name="height" maxlength ="8" />
</label>
</fieldset>
<label>
<span>Description</span>
<input name="description" />
</label>
<button type="submit">Submit</button>
</form>
<script>
const isStringValue = value => (typeof value === 'string');
const isNonEmptyStringValue = value => (isStringValue(value) && !!value.trim());
class Package {
// #data = {};
constructor(options) {
const { id, type, weight, height, description } = options;
// Object.assign(this.#data, {
Object.assign(this, {
id: isNonEmptyStringValue(id) && id || crypto.randomUUID(),
type: isNonEmptyStringValue(type) && type || 'not configured',
weight: isNonEmptyStringValue(weight) && weight || 'not provided',
height: isNonEmptyStringValue(height) && height || 'not provided',
description: isNonEmptyStringValue(description) && description || 'not provided',
});
}/*
get id() {
return this.#data.id;
}
get type() {
return this.#data.type;
}
get weight() {
return this.#data.weight;
}
get height() {
return this.#data.height;
}
get description() {
return this.#data.description;
}
set type(value) {
if (isNonEmptyStringValue(value)) {
this.#data.type = value;
}
return this.#data.type;
}
set weight(value) {
if (isNonEmptyStringValue(value)) {
this.#data.weight = value;
}
return this.#data.weight;
}
set height(value) {
if (isNonEmptyStringValue(value)) {
this.#data.height = value;
}
return this.#data.height;
}
set description(value) {
if (isNonEmptyStringValue(value)) {
this.#data.description = value;
}
return this.#data.description;
}
valueOf() {
return this.#data;
}
toString() {
return JSON.stringify(this.valueOf());
}
[Symbol.toPrimitive](hint) {
return (hint === 'string') && this.toString() || this.valueOf();
}*/
}
</script>
编辑/更新
上述解决方案可以更改为在初始化时创建包实例的解决方案(就像它已经做的那样),但根据最近的表单元素值更改有选择地更新包数据。
对于这种情况,通过真正的 getter/setter 功能来保护数据的
Package
类实现确实有意义。
function patchPackageData(evt) {
const { target: formControl, currentTarget: formNode } = evt;
const package = packageRegistry.get(formNode);
let { name: key, value } = formControl;
value = value.trim();
if (!!value) {
// update.
package[key] = value;
}
// bidirectional update.
formControl.value = package[key];
console.log('PATCH package data ...', { id: package.id, key, value: package[key] });
}
function postPackageData(formNode) {
const formData = new FormData(formNode);
const dataPatch = Object.fromEntries([...formData.entries()]);
const package = packageRegistry.get(formNode);
// post/update.
Object.assign(package, dataPatch);
Object
.keys(dataPatch)
// bidirectional update.
.forEach(key => formNode.elements[key].value = package[key]);
console.log('POST package data ...', package.valueOf());
}
function putPackageData(formNode) {
packageRegistry.set(
formNode, new Package({ id: formNode.dataset.packageId }),
);
console.log('PUT package data ...', packageRegistry.get(formNode).valueOf());
postPackageData(formNode);
}
const packageRegistry = new WeakMap;
document
.querySelectorAll('form[data-name="package-config"]')
.forEach(elmNode => {
putPackageData(elmNode);
elmNode.addEventListener('change', patchPackageData);
elmNode.addEventListener('submit', evt => evt.preventDefault());
});
body { margin: 0; }
form {
float: left;
width: 25%;
padding: 8px;
font-size: .8em;
label,
label > span {
display: block;
width: 100%;
}
label > span {
margin: 2px 0;
}
label, fieldset, [type="submit"] {
margin: 4px 0;
}
select, input {
width: 90%;
}
}
.as-console-wrapper {
left: auto!important;
bottom: 0;
width: 44%;
min-height: 100%;
}
<form data-name="package-config" data-package-id="6dfc38b8-41f0-4b4f-86d8-4aea355aef79" autocomplete="off">
<label>
<span>Type</span>
<select name ="type">
<option value="1">letter</option>
<option value="2">package</option>
</select>
</label>
<fieldset>
<legend>Measures</legend>
<label>
<span>Weight</span>
<input name="weight" maxlength="8" value="20" />
</label>
<label>
<span>Height</span>
<input name="height" maxlength ="8" />
</label>
</fieldset>
<label>
<span>Description</span>
<input name="description" value="letter 20/3" />
</label>
<button type="submit">Submit</button>
</form>
<form data-name="package-config" autocomplete="off">
<label>
<span>Type</span>
<select name ="type">
<option value="1">letter</option>
<option value="2" selected>package</option>
</select>
</label>
<fieldset>
<legend>Measures</legend>
<label>
<span>Weight</span>
<input name="weight" maxlength="8" />
</label>
<label>
<span>Height</span>
<input name="height" maxlength ="8" value="5" />
</label>
</fieldset>
<label>
<span>Description</span>
<input name="description" />
</label>
<button type="submit">Submit</button>
</form>
<script>
const isStringValue = value => (typeof value === 'string');
const isNonEmptyStringValue = value => (isStringValue(value) && !!value.trim());
class Package {
#data = {};
constructor(options) {
const { id, type, weight, height, description } = options;
Object.assign(this.#data, {
id: isNonEmptyStringValue(id) && id || crypto.randomUUID(),
type: isNonEmptyStringValue(type) && type || 'not configured',
weight: isNonEmptyStringValue(weight) && weight || 'not provided',
height: isNonEmptyStringValue(height) && height || 'not provided',
description: isNonEmptyStringValue(description) && description || 'not provided',
});
}
get id() {
return this.#data.id;
}
get type() {
return this.#data.type;
}
get weight() {
return this.#data.weight;
}
get height() {
return this.#data.height;
}
get description() {
return this.#data.description;
}
set type(value) {
if (isNonEmptyStringValue(value)) {
this.#data.type = value;
}
return this.#data.type;
}
set weight(value) {
if (isNonEmptyStringValue(value)) {
this.#data.weight = value;
}
return this.#data.weight;
}
set height(value) {
if (isNonEmptyStringValue(value)) {
this.#data.height = value;
}
return this.#data.height;
}
set description(value) {
if (isNonEmptyStringValue(value)) {
this.#data.description = value;
}
return this.#data.description;
}
valueOf() {
return this.#data;
}
toString() {
return JSON.stringify(this.valueOf());
}
[Symbol.toPrimitive](hint) {
return (hint === 'string') && this.toString() || this.valueOf();
}
}
</script>