xxx.forEach is not a function(DOM集合--类数组对象转化为数组)

xxx.forEach is not a function(DOM集合--类数组对象转化为数组)

1,错误:Uncaught TypeError: hdList.forEach is not a function

2,错误的原因

原生js获取的DOM集合是一个类数组对象,所以不能直接利用数组的方法(例如:forEach,map等),需要进行转换为数组后,才能用数组的方法!

3,6种解决办法(假如hdList是一个DOM集合)

(1),Array.from()方法

//将hdList用Array.from()方法转换为数组,并用list变量接收
let list = Array.from(hdList);

 

 

(2),用Array.prototype.slice.call(elems)方法转化为数组

 

//hdList转化为数组并用list变量接收
let list = Array.prototype.slice.call(hdList);
//添加点击事件
list.forEach((current,index) => {
	current.addEventListener('click',() => {
		animationFn(index);
	},false);
});

 

 

 

(3),用[ ...elems ]方法转化为数组

 

let list = [...hdList];//用[ ...elems ]方法转化为数组并用list接收
//添加点击事件
list.forEach((current,index) => {
	current.addEventListener('click',() => {
		animationFn(index);
	},false);
});

 

 

(4),用Array.prototype.forEach.call(elem,callback)方法

 

 

//直接对hdList集合进行循环或者map等
Array.prototype.forEach.call(hdList,function(){
//...
})
Array.prototype.map.call(hdList,function(){
//...
})

 

 

(5),用Array.prototype.forEach.apply(elem,[callback])方法

 

//添加点击事件
Array.prototype.forEach.apply(hdList,[(current,index) => {
	current.addEventListener('click',() => {
		animationFn(index);
	},false);
}]);

 

 

(6),用bind方法

 

 

//添加点击事件
Array.prototype.forEach.bind(hdList)((current,index) => {
	current.addEventListener('click',() => {
		animationFn(index);
	},false);
});


参考:

 

JavaScript中的apply()方法和call()方法使用介绍

http://www.jb51.net/article/30883.htm
 

1-DOM中-类数组对象遍历(转换)为数组

http://blog.youkuaiyun.com/bug_money/article/details/53148678

其他

[我的博客,欢迎交流!](http://rattenking.gitee.io/stone/index.html)

[我的优快云博客,欢迎交流!](https://blog.youkuaiyun.com/m0_38082783)

[微信小程序专栏](https://blog.youkuaiyun.com/column/details/18335.html)

[前端笔记专栏](https://blog.youkuaiyun.com/column/details/18321.html)

[微信小程序实现部分高德地图功能的DEMO下载](http://download.youkuaiyun.com/download/m0_38082783/10244082)

[微信小程序实现MUI的部分效果的DEMO下载](http://download.youkuaiyun.com/download/m0_38082783/10196944)

[微信小程序实现MUI的GIT项目地址](https://github.com/Rattenking/WXTUI-DEMO)

[微信小程序实例列表](http://blog.youkuaiyun.com/m0_38082783/article/details/78853722)

[前端笔记列表](http://blog.youkuaiyun.com/m0_38082783/article/details/79208205)

[游戏列表](http://blog.youkuaiyun.com/m0_38082783/article/details/79035621)

 

 

 

 

posted @ 2017-09-29 10:05 Newman·Li 阅读( ...) 评论( ...) 编辑 收藏
<think>好的,我需要帮用户解决如何将div1下所有的div2元素转换为item对象,并将每个div2中的input值作为该对象的属性,最后将这些对象组装成一个列表。用户之前的提问是关于获取所有input值并组成数组,现在更进一步,需要结构化为对象数组。 首先,我需要理解用户的需求。用户希望每个div2对应一个item对象,每个input的name或class作为键,value作为值。例如,如果每个div2里有多个input,比如name和age,那么每个item对象应该包含{name: "xxx", age: "yyy"},然后所有这样的对象组成一个数组。 接下来,我需要考虑如何用JavaScript实现。可能需要遍历每个div2元素,然后在每个div2中查找所有input,提取它们的name属性和value,组合成对象。这里需要注意,如果input没有name属性,可能需要用其他标识符,比如class,但通常name更合适,因为它是表单元素的常用属性。 用户之前的回答中提到了使用getElementsByClassName和querySelector,这次可能需要更详细的选择器来获取每个div2中的input。同时,要考虑动态生成的元素是否已经加载到DOM中,否则选择器可能无法找到它们。 然后,如何组装成对象数组。可能需要使用map方法,或者循环遍历每个div2,然后对每个div2中的input进行遍历,将它们的name和value收集到对象中,再推入数组。 另外,用户提到“input对应item里面的key”,这可能需要明确input的name属性作为key,value作为值。例如,如果input有name="username",那么item对象的username属性就是该input的值。 可能的步骤: 1. 获取div1下的所有div2元素。 2. 遍历每个div2元素。 3. 对于每个div2,查找所有的input元素。 4. 将每个input的name属性和value组合成一个对象。 5. 将所有对象推入数组。 需要注意的是,如果div2中有多个input,每个input都应该成为item对象的一个属性。因此,每个div2可能对应多个键值对,而不仅仅是一个。 可能的代码结构: 使用querySelectorAll获取所有div2,然后使用Array.from转换为数组,再使用map方法处理每个div2。在map的回调中,使用querySelectorAll获取该div2下的所有input,然后使用Array.from和reduce方法将input转换为对象。 例如: const items = Array.from(document.querySelectorAll('#div1 .div2')).map(div2 => { const inputs = div2.querySelectorAll('input'); return Array.from(inputs).reduce((obj, input) => { obj[input.name] = input.value; return obj; }, {}); }); 这样,每个div2会被转换成一个对象,所有input的name和value作为属性,最后得到一个对象数组。 还需要考虑异常情况,比如input没有name属性,这时候可能需要跳过或使用其他标识符。同时,处理同名input的情况,比如多个同名的radio或checkbox,但用户的问题可能更侧重于文本输入的情况。 另外,用户可能希望在前端处理这些数据,然后通过AJAX发送到后端。所以需要确保生成的数组结构正确,比如每个对象的键对应后端的字段名。 可能还需要在克隆div2时确保每个input都有唯一的name,或者在克隆时保持name属性一致,以便正确映射到对象的键。 总结,解决方案需要遍历每个div2,收集其中的input的name和value,构建对象,并组装成数组。代码需要兼顾原生JS和可能的jQuery实现,根据用户的技术栈选择合适的方法。</think>以下是实现将`div1`下所有`div2`转换为对象数组的详细解决方案: --- ### **HTML 结构示例** 假设每个`div2`包含多个带`name`属性的输入字段: ```html <div id="div1"> <div class="div2"> <input type="text" name="username" class="data-input"> <input type="number" name="age" class="data-input"> </div> <div class="div2"> <input type="text" name="username" class="data-input"> <input type="number" name="age" class="data-input"> </div> </div> ``` --- ### **JavaScript 实现** #### 方法一:原生 JavaScript ```javascript function getItemList() { const div1 = document.getElementById("div1"); const div2Elements = div1.getElementsByClassName("div2"); const itemList = []; // 遍历每个div2 Array.from(div2Elements).forEach(div2 => { const inputs = div2.querySelectorAll("input[name]"); // 限定必须包含name属性 const item = {}; // 遍历每个input,提取name和value inputs.forEach(input => { const key = input.name; // 使用name作为对象键 const value = input.value; item[key] = value; }); itemList.push(item); }); return itemList; } // 调用示例 const result = getItemList(); console.log(result); // 输出示例:[{username: "John", age: "25"}, {username: "Alice", age: "30"}] ``` #### 方法二:使用 jQuery(简化代码) ```javascript function getItemListJQ() { return $("#div1 .div2").map(function() { const item = {}; $(this).find("input[name]").each(function() { item[this.name] = $(this).val(); }); return item; }).get(); } // 调用示例 $("#btnSubmit").click(() => { const data = getItemListJQ(); console.log(data); }); ``` --- ### **关键点解析** 1. **定位元素**: - 使用`getElementsByClassName("div2")`或`querySelectorAll("#div1 .div2")`获取所有`div2` - 通过`input[name]`选择器确保只操作有标识属性的输入框 2. **动态键值映射**: ```javascript inputs.forEach(input => { item[input.name] = input.value; // 动态设置对象属性 }); ``` - 利用`input.name`作为键名,直接关联后端字段(如数据库列名) 3. **处理特殊场景**: ```javascript // 处理空值或未命名input if (input.name && input.value.trim() !== "") { item[input.name] = input.value; } ``` --- ### **数据结构优化建议** 1. **统一键名规范**: - 确保所有`div2`内的`input`使用一致的`name`属性 - 示例:`name="email"`代替`name="user_email"` 2. **嵌套对象支持**: ```javascript // 若需要层级结构(如 address.city) item["address"] = { city: $("#city").val(), street: $("#street").val() }; ``` 3. **数据类型转换**: ```javascript // 将数值型输入转为Number if (input.type === "number") { item[input.name] = Number(input.value); } ``` --- ### **数据提交示例** 将对象数组通过 AJAX 发送到服务端: ```javascript // 原生JavaScript fetch("/submit", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ items: getItemList() }) }); // jQuery $.ajax({ url: "/submit", type: "POST", data: JSON.stringify(getItemListJQ()), contentType: "application/json" }); ``` --- ### **注意事项** 1. **克隆一致性**: - 动态克隆时需保留`name`属性 ```javascript function cloneDiv2() { const template = document.querySelector(".div2"); const clone = template.cloneNode(true); clone.querySelectorAll("input").forEach(input => input.value = ""); div1.appendChild(clone); } ``` 2. **唯一性校验**: ```javascript // 检查是否有重复键名 const keys = new Set(); inputs.forEach(input => { if (keys.has(input.name)) { throw new Error(`重复的字段名: ${input.name}`); } keys.add(input.name); }); ``` 3. **响应式更新**: ```javascript // 监听输入变化实时更新数据 document.getElementById("div1").addEventListener("input", () => { const latestData = getItemList(); // 更新视图或状态管理 }); ``` --- 通过上述方法,可以高效地将动态生成的`div2`内容转换为结构化的对象列表,适用于表单批量提交、数据预览等场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值