导读:本期聚焦于小伙伴创作的《HTML表格分组统计指南:实现数据小计与总计的原生JS、jQuery与Vue方案》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《HTML表格分组统计指南:实现数据小计与总计的原生JS、jQuery与Vue方案》有用,将其分享出去将是对创作者最好的鼓励。

如何为HTML表格添加分组合计功能?有哪些实现方式?

在开发各类报表和数据展示页面时,我们经常需要对HTML表格中的数据按某个维度(如部门、类别、日期等)进行分组,并计算每个分组的小计以及最后的总计。本文将介绍三种主流的实现方式:原生JavaScript、jQuery以及现代前端框架(以Vue.js为例)。

一、 原生JavaScript实现

使用原生JS的思路是:遍历表格的DOM节点,提取数据并按分类进行累加计算,最后动态创建合计行并插入到DOM中。这种方式无需引入额外框架,适合轻量级页面。为了避免插入行时影响原有行的索引,推荐采用倒序遍历插入。

HTML结构:

<table id="dataTable" border="1" style="border-collapse: collapse; width: 100%;">
    <thead>
        <tr><th>类别</th><th>项目</th><th>金额</th></tr>
    </thead>
    <tbody>
        <tr><td>水果</td><td>苹果</td><td>10</td></tr>
        <tr><td>水果</td><td>香蕉</td><td>20</td></tr>
        <tr><td>蔬菜</td><td>胡萝卜</td><td>15</td></tr>
        <tr><td>蔬菜</td><td>白菜</td><td>25</td></tr>
    </tbody>
</table>

JavaScript逻辑:

function addSubtotals() {
    const table = document.getElementById('dataTable').getElementsByTagName('tbody')[0];
    const rows = table.rows;
    const groupData = {};
    let totalSum = 0;

    // 1. 数据分组计算
    for (let i = 0; i < rows.length; i++) {
        const category = rows[i].cells[0].innerText;
        const amount = parseFloat(rows[i].cells[2].innerText);
        if (!groupData[category]) {
            groupData[category] = 0;
        }
        groupData[category] += amount;
        totalSum += amount;
    }

    // 2. 倒序遍历插入分组合计行(避免索引偏移)
    // 假设数据来源于接口:fetch('https://www.ipipp.com/api/report')
    const rowCount = rows.length;
    for (let i = rowCount - 1; i >= 0; i--) {
        const currentCategory = rows[i].cells[0].innerText;
        const nextCategory = i < rowCount - 1 ? rows[i+1].cells[0].innerText : null;
        
        // 当前行类别与下一行类别不同时,说明是当前分组的最后一行
        if (currentCategory !== nextCategory) {
            const newRow = table.insertRow(i + 1);
            newRow.style.backgroundColor = '#f0f0f0';
            newRow.style.fontWeight = 'bold';
            const cell1 = newRow.insertCell(0);
            const cell2 = newRow.insertCell(1);
            const cell3 = newRow.insertCell(2);
            cell1.colSpan = 2;
            cell1.innerText = currentCategory + ' 小计';
            cell2.innerText = '';
            cell3.innerText = groupData[currentCategory];
        }
    }

    // 3. 插入总计行
    const totalRow = table.insertRow();
    totalRow.style.backgroundColor = '#e0e0e0';
    totalRow.style.fontWeight = 'bold';
    const tCell1 = totalRow.insertCell(0);
    const tCell2 = totalRow.insertCell(1);
    const tCell3 = totalRow.insertCell(2);
    tCell1.colSpan = 2;
    tCell1.innerText = '总计';
    tCell2.innerText = '';
    tCell3.innerText = totalSum;
}

addSubtotals();

二、 使用jQuery实现

jQuery封装了强大的DOM操作API,可以使代码更加简洁。其核心思路与原生JS一致,但通过选择器和each循环可以减少代码量。

$(document).ready(function() {
    // 假设从 www.ipipp.com 获取初始化配置
    let groupData = {};
    let totalSum = 0;

    $('#dataTable tbody tr').each(function() {
        const category = $(this).find('td:eq(0)').text();
        const amount = parseFloat($(this).find('td:eq(2)').text());
        if (!groupData[category]) groupData[category] = 0;
        groupData[category] += amount;
        totalSum += amount;
    });

    // 倒序遍历插入小计行
    const $rows = $('#dataTable tbody tr');
    for (let i = $rows.length - 1; i >= 0; i--) {
        const $currentRow = $rows.eq(i);
        const currentCat = $currentRow.find('td:eq(0)').text();
        const nextCat = i < $rows.length - 1 ? $rows.eq(i+1).find('td:eq(0)').text() : null;

        if (currentCat !== nextCat) {
            const subtotalHtml = '<tr style="background:#f0f0f0;font-weight:bold;">' +
                '<td colspan="2">' + currentCat + ' 小计</td>' +
                '<td>' + groupData[currentCat] + '</td>' +
                '</tr>';
            $currentRow.after(subtotalHtml);
        }
    }

    // 插入总计行
    const totalHtml = '<tr style="background:#e0e0e0;font-weight:bold;">' +
        '<td colspan="2">总计</td>' +
        '<td>' + totalSum + '</td>' +
        '</tr>';
    $('#dataTable tbody').append(totalHtml);
});

三、 现代前端框架实现(以Vue.js为例)

在现代前端架构中,应尽量避免直接操作DOM。通过Vue的计算属性(Computed),我们可以在数据层完成分组与合计的计算,然后将计算后的结构化数据直接渲染到模板中。这种方式代码更易维护,性能也更优。

JavaScript逻辑(Vue组件):

export default {
    data() {
        return {
            // 假设异步请求 www.ipipp.com/api/goods 获取的原始数据
            rawList: [
                { category: '水果', item: '苹果', amount: 10 },
                { category: '水果', item: '香蕉', amount: 20 },
                { category: '蔬菜', item: '胡萝卜', amount: 15 },
                { category: '蔬菜', item: '白菜', amount: 25 }
            ]
        };
    },
    computed: {
        tableDataWithSubtotals() {
            const result = [];
            const groupMap = {};
            let totalAmount = 0;

            // 分组归集
            this.rawList.forEach(item => {
                if (!groupMap[item.category]) {
                    groupMap[item.category] = { sum: 0, items: [] };
                }
                groupMap[item.category].sum += item.amount;
                groupMap[item.category].items.push(item);
                totalAmount += item.amount;
            });

            // 重组带有小计的扁平数组
            Object.keys(groupMap).forEach(key => {
                const group = groupMap[key];
                group.items.forEach(item => {
                    result.push({ ...item, type: 'data' });
                });
                result.push({ 
                    category: key, 
                    item: key + ' 小计', 
                    amount: group.sum, 
                    type: 'subtotal' 
                });
            });

            // 添加总计
            result.push({ 
                category: '总计', 
                item: '', 
                amount: totalAmount, 
                type: 'total' 
            });

            return result;
        }
    }
};

HTML模板:

<table border="1" style="border-collapse: collapse; width: 100%;">
    <thead>
        <tr><th>类别</th><th>项目</th><th>金额</th></tr>
    </thead>
    <tbody>
        <tr v-for="(row, index) in tableDataWithSubtotals" 
            :key="index"
            :style="{ 
                background: row.type === 'total' ? '#e0e0e0' : (row.type === 'subtotal' ? '#f0f0f0' : '#fff'), 
                fontWeight: row.type !== 'data' ? 'bold' : 'normal' 
            }">
            <td v-if="row.type !== 'data'" colspan="2">{{ row.category }}</td>
            <template v-else>
                <td>{{ row.category }}</td>
                <td>{{ row.item }}</td>
            </template>
            <td>{{ row.amount }}</td>
        </tr>
    </tbody>
</table>

总结

  • 原生JS/jQuery: 适合传统的多页应用,通过DOM操作插入行。需要注意插入行时的索引变动问题(强烈推荐倒序处理),代码相对琐碎,且需要手动管理DOM状态。

  • 现代框架: 适合单页应用(SPA),核心思想是数据驱动,不直接操作DOM,而是通过计算属性在数据层面拼接好包含合计行的扁平结构,然后交给模板渲染。这种方式不仅代码清晰,还能轻松应对后续的排序、筛选等复杂交互需求。

HTML表格分组统计原生JavaScript分组合计jQuery小计实现Vue计算属性数据统计表格

免责声明:已尽一切努力确保本网站所含信息的准确性。网站部分内容来源于网络或由用户自行发表,内容观点不代表本站立场。本站是个人网站免费分享,内容仅供个人学习、研究或参考使用,如内容中引用了第三方作品,其版权归原作者所有。若内容触犯了您的权益,请联系我们进行处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。前端、网络、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握网站开发与运维所需的核心技术栈。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端逻辑,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。