
在web开发中,我们经常需要从后端获取一组数据,并根据数据中的某个共同标识(例如student.id)进行分组,然后将这些分组后的数据展示在前端页面上。更进一步,每个分组还需要提供一个“全选”功能,允许用户一次性选中或取消选中该分组内的所有子项。
假设我们有以下结构的数据列表,其中包含学生的详细信息:
const res = {
List: [
{"School information":{RegId: 1,Name : "SJ"},ParentInfo:{Id:0,Name:"Abc"},Student:{Id:1,Name:"Student1"}},
{"School information":{RegId: 1,Name : ""},ParentInfo:{Id:0,Name:""},Student:{Id:5,Name:"Student6"}},
{"School information":{RegId: 1,Name : ""},ParentInfo:{Id:0,Name:""},Student:{Id:1,Name:"Student3"}},
{"School information":{RegId: 1,Name : ""},ParentInfo:{Id:0,Name:""},Student:{Id:5,Name:"Student5"}},
{"School information":{RegId: 1,Name : ""},ParentInfo:{Id:0,Name:""},Student:{Id:1,Name:"Student4"}},
{"School information":{RegId: 1,Name : ""},ParentInfo:{Id:0,Name:""},Student:{Id:7,Name:"Student9"}},
{"School information":{RegId: 1,Name : ""},ParentInfo:{Id:0,Name:""},Student:{Id:7,Name:"Student11"}}
]
};我们的目标是将其渲染成如下所示的结构,其中每个Student.Id对应的学生姓名被归为一组,并且每组顶部有一个“Select All Students”复选框:
Select All Studentds // with check box Student1 Student3 Student4 Select All Studentds // with check box Student5 Student6 Select All Studentds // with check box Student9 Student11
解决此问题主要分为两个核心步骤:数据分组和前端渲染与交互。
首先,我们需要将原始列表中的学生数据根据Student.Id进行分组。JavaScript的Array.prototype.reduce()方法非常适合这种聚合操作。
立即学习“Java免费学习笔记(深入)”;
const groupedStudents = res.List.reduce((accumulator, currentItem) => {
const studentId = currentItem.Student.Id;
const studentName = currentItem.Student.Name;
// 如果accumulator中还没有这个ID的数组,则初始化一个空数组
if (!accumulator[studentId]) {
accumulator[studentId] = [];
}
// 将学生姓名添加到对应ID的数组中
accumulator[studentId].push(studentName);
return accumulator;
}, {}); // 初始值是一个空对象
/*
groupedStudents 的结果将是:
{
'1': ['Student1', 'Student3', 'Student4'],
'5': ['Student6', 'Student5'],
'7': ['Student9', 'Student11']
}
*/在这个reduce操作中:
数据分组完成后,下一步是将其渲染到HTML页面上,并实现“全选”功能。
我们需要一个容器元素来承载动态生成的学生列表,例如一个div:
<div id="container"></div>
我们将遍历groupedStudents对象(使用Object.values()获取所有分组数组),然后为每个分组生成对应的HTML结构。
const container = document.getElementById("container");
container.innerHTML = Object.values(groupedStudents)
.map(group => {
// 为每个分组生成一个包含“全选”复选框和学生姓名的div
const groupHeader = `<div>
<label>Select All Students <input type="checkbox" class="group-select-all"></label><br>`;
// 为分组内的每个学生生成一个复选框
const studentItems = group.map(studentName =>
`<label><input type="checkbox">${studentName}</label>`
).join("<br>"); // 每个学生项之间用<br>分隔
return groupHeader + studentItems + '</div>';
})
.join(""); // 各个分组之间不需要额外的分隔符最后,我们需要为每个“全选”复选框添加事件监听器,使其能够控制其所在分组内所有学生复选框的选中状态。
document.querySelectorAll(".group-select-all").forEach(selectAllCheckbox => {
selectAllCheckbox.addEventListener("click", () => {
// 找到当前“全选”复选框所属的最近的div容器
const groupDiv = selectAllCheckbox.closest("div");
// 选中该div内所有的复选框(除了“全选”本身,但这里选择器会包含)
// 更好的做法是排除掉自身的class,但由于我们目标是所有[type=checkbox],通常也无妨
groupDiv.querySelectorAll("[type=checkbox]").forEach(checkbox => {
checkbox.checked = selectAllCheckbox.checked;
});
});
});将以上所有代码整合,得到一个完整的解决方案:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript 分组数据与全选功能</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
#container > div {
border: 1px solid #eee;
padding: 15px;
margin-bottom: 20px;
background-color: #f9f9f9;
border-radius: 5px;
}
label { display: block; margin-bottom: 5px; }
.group-select-all { margin-right: 5px; }
</style>
</head>
<body>
<h1>学生列表分组与全选示例</h1>
<div id="container"></div>
<script>
const res = { List:
[{"School information":{RegId: 1,Name : "SJ"},ParentInfo:{Id:0,Name:"Abc"},Student:{Id:1,Name:"Student1"}},
{"School information":{RegId: 1,Name : ""}, ParentInfo:{Id:0,Name:""}, Student:{Id:5,Name:"Student6"}},
{"School information":{RegId: 1,Name : ""}, ParentInfo:{Id:0,Name:""}, Student:{Id:1,Name:"Student3"}},
{"School information":{RegId: 1,Name : ""}, ParentInfo:{Id:0,Name:""}, Student:{Id:5,Name:"Student5"}},
{"School information":{RegId: 1,Name : ""}, ParentInfo:{Id:0,Name:""}, Student:{Id:1,Name:"Student4"}},
{"School information":{RegId: 1,Name : ""}, ParentInfo:{Id:0,Name:""}, Student:{Id:7,Name:"Student9"}},
{"School information":{RegId: 1,Name : ""}, ParentInfo:{Id:0,Name:""}, Student:{Id:7,Name:"Student11"}}]};
// 1. 数据分组
const groupedStudents = res.List.reduce((accumulator, currentItem) => {
const studentId = currentItem.Student.Id;
const studentName = currentItem.Student.Name;
(accumulator[studentId] ??= []).push(studentName);
return accumulator;
}, {});
// 2. 前端渲染
const container = document.getElementById("container");
container.innerHTML = Object.values(groupedStudents)
.map(group =>
`<div>
<label>Select All Students <input type="checkbox" class="group-select-all"></label><br>`
+ group.map(studentName => `<label><input type="checkbox">${studentName}</label>`).join("<br>")
+ `</div>`
).join("");
// 3. 添加“全选”功能交互
document.querySelectorAll(".group-select-all").forEach(selectAllCheckbox => {
selectAllCheckbox.addEventListener("click", () => {
const groupDiv = selectAllCheckbox.closest("div");
groupDiv.querySelectorAll("[type=checkbox]").forEach(checkbox => {
checkbox.checked = selectAllCheckbox.checked;
});
});
});
</script>
</body>
</html>// 使用Map进行分组
const groupedStudentsMap = res.List.reduce((map, item) => {
const studentId = item.Student.Id;
const studentName = item.Student.Name;
if (!map.has(studentId)) {
map.set(studentId, []);
}
map.get(studentId).push(studentName);
return map;
}, new Map());
// 渲染时使用 Array.from(groupedStudentsMap.values()) 或 [...groupedStudentsMap.values()]本教程详细展示了如何利用JavaScript的reduce方法对复杂数据结构进行高效分组,并通过DOM操作和事件监听实现了动态渲染带有“全选”功能的交互式列表。这种模式在处理和展示结构化数据时非常常见,掌握这些技术将有助于开发者构建更灵活和用户友好的Web界面。通过模块化和考虑性能及可访问性,可以进一步提升应用的质量。
以上就是JavaScript中基于ID分组列表数据并实现全选功能的教程的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号