【问题标题】:Iterate over an HTMLcollection to dynamically define values in a constructor function?遍历 HTMLcollection 以在构造函数中动态定义值?
【发布时间】:2016-05-03 18:35:19
【问题描述】:

我会直接进入描述和示例代码,因为我敢打赌,你们中的许多人都和我一样对标题感到困惑(尽我所能)。

情况:我有一个表单,它使用构造函数将输入数据提交给对象的新实例。

当前代码:

// 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);

问题:将数组作为参数传递并手动分配每个索引对我来说感觉非常脆弱。如果我要扩展表单的数据收集,我将不得不手动将每个新值分配为单独的变量。如果您要遍历数组并动态地将值分配给构造函数中的变量,那么语法或模式是什么?先感谢您。非常感谢任何和所有帮助。

所需代码示例

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);

【问题讨论】:

  • 抱歉,但是您的示例将 Task 与 DOM 紧密结合在一起,我认为我的建议是更好地分离关注点。

标签: javascript oop constructor htmlcollection


【解决方案1】:

只需将表单元素的名称用作对象中的属性名称即可。

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

不要在循环中使用return,这将在处理完数组中的第一个元素后结束构造函数,并忽略其余部分。

【讨论】:

  • 谢谢,这正是我想要的。感谢编辑和答案!
【解决方案2】:

我只是分别取三个参数,让调用者判断哪个是标题、截止日期或状态

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

现在您的调用者可以通过使用 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);

现在您的构造函数不依赖于数组中的顺序,甚至不依赖于它们是 DOM 元素。

您始终可以签订合同,其中特定输入通过数据属性映射到任务字段

<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);

【讨论】:

  • 我知道你在做什么,我可能会选择这个选项。我对您的解决方案的唯一反对意见是,如果我决定向表单添加更多输入字段,它仍然需要我手动更改集合代码。对此有什么想法吗?感谢您的快速回复。
  • 您的意思是,如果您向Task 对象添加更多字段?我所做的是将Task 与表单完全解耦,这样您就可以修改表单而不必修改Task。发布您的意思的示例,包括 HTML
【解决方案3】:

我会使用关联数组 -

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

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

这使您的数组在语义上有意义且不那么脆弱。表单是否展开也没关系,只要不更改名称,它将继续工作。

这也意味着您不必在每次展开表单时更改构造函数的调用签名,您只需更改主体以处理数组中的新元素(或不更改,由您选择)。

【讨论】:

  • Cringe... 请不要将数组用作地图(或关联数组)。这是来自没有正确学习 JavaScript 的 PHP 开发人员的术语。
  • 记住滥用数组作为“关联数组”将使length 属性毫无意义。
  • 无论如何都应该妥善记录,这几乎不是一个巨大的负担。
  • 谢谢 Jeremy,但我需要一个完整的 .length 方法来迭代 HTMLcollection。至于 JavaScript 是“一种糟糕的语言”,这只是你的看法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-09
  • 2019-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-27
相关资源
最近更新 更多