简体   繁体   English

迭代 HTMLcollection 以在构造函数中动态定义值?

[英]Iterate over an HTMLcollection to dynamically define values in a constructor function?

i'll get right to the description and example code as i bet many of you are as confused about the title as i am (tried my best).我会直接看描述和示例代码,因为我敢打赌你们中的许多人和我一样对标题感到困惑(尽我所能)。

Situation: I have a form that submits input data to a new instance of an object, using a constructor function.情况:我有一个表单,它使用构造函数将输入数据提交给对象的新实例。

CURRENT CODE:当前代码:

// Selectors
var submit = document.getElementById('submit-btn');
var formValues = document.getElementsByClassName('input');

// ** Task Object
function Task(arrayOfValues) {
  this.title = arrayOfValues[0].value;
  this.deadline = arrayOfValues[1].value;
  this.status = arrayOfValues[2].value;
}
submit.addEventListener('click', function(e) {
  e.preventDefault();
  var newTask = new Task(formValues);  
}, false);

Problem: Passing the array as an argument and assigning each index manually feels incredibly brittle to me.问题:将数组作为参数传递并手动分配每个索引对我来说感觉非常脆弱。 If i were to extend the data collection of the form i would have to manually assign each new value as a separate variable.如果我要扩展表单的数据收集,我将不得不手动将每个新值分配为一个单独的变量。 What is the syntax or pattern if you will for iterating over an array and dynamically assigning values to variables in a constructor function ?如果要迭代数组并在构造函数中为变量动态赋值,则语法或模式是什么? Thank you in advance.先感谢您。 Any and all help is much appreciated.非常感谢任何和所有帮助。

EXAMPLE of desired CODE所需代码示例

var formValues = document.getElementsByClassName('input');

// ** Task Object
function Task(arrayOfValues) {
  this.values = arrayOfValues;

  for (var i=0;i<this.values.length;i++) {
    var key = this.values[i].getAttribute('name'); 
    // This should be used with "this" to reference key ie. "this.title, this.deadline, this.status ect...

    var value = this.values[i].value;
    // This will be the value associated with each key reference ie. "this"

    return this[key] = value;
    // is this even possible ?        
  }

}
submit.addEventListener('click', function(e) {
  e.preventDefault();
  var newTask = new Task(formValues);  
}, false);

I would just take the three parameters separately, let the caller figure out which one is the title, deadline or status我就分别取三个参数,让调用者弄清楚哪一个是标题、截止日期或状态

function Task(title, deadline, status) {
  this.title = title;
  this.deadline = deadline;
  this.status = status;
}

Now your callers can figure out which one is which by using IDs, data-attributes, or anything they want.现在您的呼叫者可以通过使用 ID、数据属性或他们想要的任何东西来确定哪个是哪个。

<input id="title-x"> <input id="deadline"> <input id="status">

submit.addEventListener('click', function(e) {
  e.preventDefault();
  var getVal = function(id) { return  document.getElementById(id).value; }
  var newTask = new Task(getVal('title-x'), getVal('deadline'), getVal('status'));  
}, false);

Now your constructor doesn't rely on the order within the array, or even that they are DOM elements.现在您的构造函数不依赖于数组中的顺序,甚至不依赖于它们是 DOM 元素。

You could always have a contract where a specific input maps to a task field through data-attributes你总是可以有一个合同,其中一个特定的输入通过数据属性映射到一个任务字段

<input data-task-field="title">
<input data-task-field="deadline">
<input data-task-field="status">
<input data-task-field="newField">

/**
 * @param {object} taskDescription 
 * @param {string} taskDescription.title
 * @param {string} taskDescription.deadline
 * @param {string} taskDescription.status
 * @param {string} taskDescription.newField
 */
function Task(taskDescription) {
  this.task = taskDescription;
}

submit.addEventListener('click', function(e) {
  e.preventDefault();
  var tasks = document.querySelectorAll('input[data-task-field]');
  var taskSpec = {};
  for (var i=0; i < tasks.length; i++) {
    taskSpec[tasks.getAttribute('data-task-field')] = tasks.value; 
  }
  var newTask = new Task(taskSpec);  
}, false);

Just use the names of the form elements as the property names in the object.只需使用表单元素的名称作为对象中的属性名称。

function Task(arrayOfValues) {
  for (var i=0;i<arrayOfValues.length;i++) {
    var key = arrayOfValues[i].name;
    var value = arrayOfValues[i].value;
    this[key] = value;       
  }
}

Don't use return inside the loop, that will end the constructor after processing the first element in the array, and ignore the rest.不要在循环内使用return ,这将在处理数组中的第一个元素后结束构造函数,并忽略其余部分。

I would use an associative array -我会使用关联数组 -

http://www.w3schools.com/js/js_arrays.asp http://www.w3schools.com/js/js_arrays.asp

var assArray = [];
assArray["title"] = document.getElementbyID(......)

That makes your array semantically meaningful and less brittle.这使您的数组在语义上有意义且不那么脆弱。 It doesn't matter if you expand the form, so long as you don't change the names it will continue to work.如果您扩展表单并不重要,只要您不更改名称,它就会继续工作。

It also means you don't have to change the call signature of your constructor each time you expand the form, you only have to alter the body to deal with the new elements in the array (or not, as you so choose).这也意味着您不必在每次展开表单时更改构造函数的调用签名,您只需更改主体以处理数组中的新元素(或不更改,根据您的选择)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM