You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UIKit表格如何添加列头排序与分页功能?

为UIKit表格添加排序与分页功能

好的,我来帮你搞定UIKit表格的排序和分页功能——UIKit本身没有直接内置这俩表格增强功能,但结合一点自定义JS和UIKit的现有组件就能轻松实现。下面是完整的实现方案,包含代码示例和详细解释:

一、核心实现思路

  • 排序功能:给可排序的表头添加点击事件,切换排序方向(升序/降序/默认),通过JS对表格行数据进行排序并重新渲染,同时用UIKit的图标显示排序状态。
  • 分页功能:使用UIKit的uk-pagination组件做分页导航,通过JS控制表格行的显示/隐藏,根据总数据量计算分页数量。

二、完整代码实现

<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/uikit@3.16.22/dist/css/uikit.min.css" />
    <script src="https://cdn.jsdelivr.net/npm/uikit@3.16.22/dist/js/uikit.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/uikit@3.16.22/dist/js/uikit-icons.min.js"></script>
    <style>
        /* 给可排序表头添加指针光标和间距 */
        .sortable {
            cursor: pointer;
            position: relative;
            padding-right: 25px;
        }
        /* 排序箭头的位置调整 */
        .sortable .uk-icon {
            position: absolute;
            right: 8px;
            top: 50%;
            transform: translateY(-50%);
            opacity: 0.5;
        }
        .sortable.active .uk-icon {
            opacity: 1;
        }
    </style>
</head>
<body>
    <div class="uk-container uk-margin-top">
        <!-- 带排序功能的表格 -->
        <table class="uk-table uk-table-hover uk-table-divider" id="dataTable">
            <thead>
                <tr>
                    <!-- 给需要排序的表头添加sortable类 -->
                    <th class="sortable" data-sort-index="0">Table Heading <span uk-icon="chevron-up" class="sort-icon"></span></th>
                    <th class="sortable" data-sort-index="1">Table Heading <span uk-icon="chevron-up" class="sort-icon"></span></th>
                    <th class="sortable" data-sort-index="2">Table Heading <span uk-icon="chevron-up" class="sort-icon"></span></th>
                    <th>Actions</th>
                </tr>
            </thead>
            <tbody id="tableBody">
                <tr>
                    <td>Apple</td>
                    <td>2024-01-15</td>
                    <td>$10</td>
                    <td><span uk-icon="heart"></span></td>
                </tr>
                <tr>
                    <td>Banana</td>
                    <td>2024-01-10</td>
                    <td>$5</td>
                    <td><span uk-icon="heart"></span></td>
                </tr>
                <tr>
                    <td>Cherry</td>
                    <td>2024-01-20</td>
                    <td>$15</td>
                    <td><span uk-icon="heart"></span></td>
                </tr>
                <tr>
                    <td>Date</td>
                    <td>2024-01-05</td>
                    <td>$8</td>
                    <td><span uk-icon="heart"></span></td>
                </tr>
                <tr>
                    <td>Elderberry</td>
                    <td>2024-01-25</td>
                    <td>$12</td>
                    <td><span uk-icon="heart"></span></td>
                </tr>
            </tbody>
        </table>

        <!-- 分页组件 -->
        <ul class="uk-pagination uk-flex-center uk-margin-top" id="pagination">
            <!-- 分页按钮会通过JS动态生成 -->
        </ul>
    </div>

    <script>
        // 全局变量:当前排序列、排序方向、当前页码、每页显示行数
        let currentSortIndex = -1;
        let sortDirection = 'asc'; // asc:升序, desc:降序
        let currentPage = 1;
        const rowsPerPage = 2;

        // 获取表格元素
        const tableBody = document.getElementById('tableBody');
        const pagination = document.getElementById('pagination');
        const sortableHeaders = document.querySelectorAll('.sortable');

        // 初始化:渲染分页和默认排序
        document.addEventListener('DOMContentLoaded', () => {
            renderPagination();
            showPage(currentPage);
        });

        // -------------------------- 排序功能实现 --------------------------
        // 给每个可排序表头添加点击事件
        sortableHeaders.forEach(header => {
            header.addEventListener('click', () => {
                const index = parseInt(header.dataset.sortIndex);
                // 切换排序方向:如果点击的是当前排序列,反转方向;否则默认升序
                if (currentSortIndex === index) {
                    sortDirection = sortDirection === 'asc' ? 'desc' : 'asc';
                } else {
                    currentSortIndex = index;
                    sortDirection = 'asc';
                }
                // 更新表头图标状态
                updateSortIcons(header);
                // 执行排序
                sortTable(index, sortDirection);
                // 排序后回到第一页
                currentPage = 1;
                renderPagination();
                showPage(currentPage);
            });
        });

        // 更新排序图标显示
        function updateSortIcons(activeHeader) {
            // 重置所有表头的图标和状态
            sortableHeaders.forEach(h => {
                h.classList.remove('active');
                const icon = h.querySelector('.sort-icon');
                icon.setAttribute('uk-icon', 'chevron-up');
            });
            // 设置当前激活表头的图标和状态
            activeHeader.classList.add('active');
            const icon = activeHeader.querySelector('.sort-icon');
            icon.setAttribute('uk-icon', sortDirection === 'asc' ? 'chevron-up' : 'chevron-down');
        }

        // 表格排序逻辑
        function sortTable(columnIndex, direction) {
            const rows = Array.from(tableBody.querySelectorAll('tr'));
            // 排序行数据
            rows.sort((a, b) => {
                const aText = a.cells[columnIndex].textContent.trim();
                const bText = b.cells[columnIndex].textContent.trim();
                // 判断是否为数字/日期类型,做对应排序
                if (!isNaN(aText) && !isNaN(bText)) {
                    return direction === 'asc' ? parseFloat(aText) - parseFloat(bText) : parseFloat(bText) - parseFloat(aText);
                } else if (!isNaN(Date.parse(aText)) && !isNaN(Date.parse(bText))) {
                    return direction === 'asc' ? new Date(aText) - new Date(bText) : new Date(bText) - new Date(aText);
                } else {
                    // 字符串排序
                    return direction === 'asc' ? aText.localeCompare(bText) : bText.localeCompare(aText);
                }
            });
            // 重新渲染表格行
            tableBody.innerHTML = '';
            rows.forEach(row => tableBody.appendChild(row));
        }

        // -------------------------- 分页功能实现 --------------------------
        // 渲染分页按钮
        function renderPagination() {
            const totalRows = tableBody.querySelectorAll('tr').length;
            const totalPages = Math.ceil(totalRows / rowsPerPage);
            // 清空现有分页按钮
            pagination.innerHTML = '';

            // 上一页按钮
            const prevItem = document.createElement('li');
            prevItem.innerHTML = `<a href="#"><span uk-pagination-previous></span></a>`;
            prevItem.classList.toggle('uk-disabled', currentPage === 1);
            prevItem.addEventListener('click', (e) => {
                e.preventDefault();
                if (currentPage > 1) {
                    currentPage--;
                    renderPagination();
                    showPage(currentPage);
                }
            });
            pagination.appendChild(prevItem);

            // 页码按钮
            for (let i = 1; i <= totalPages; i++) {
                const pageItem = document.createElement('li');
                pageItem.innerHTML = `<a href="#">${i}</a>`;
                pageItem.classList.toggle('uk-active', i === currentPage);
                pageItem.addEventListener('click', (e) => {
                    e.preventDefault();
                    currentPage = i;
                    renderPagination();
                    showPage(currentPage);
                });
                pagination.appendChild(pageItem);
            }

            // 下一页按钮
            const nextItem = document.createElement('li');
            nextItem.innerHTML = `<a href="#"><span uk-pagination-next></span></a>`;
            nextItem.classList.toggle('uk-disabled', currentPage === totalPages);
            nextItem.addEventListener('click', (e) => {
                e.preventDefault();
                if (currentPage < totalPages) {
                    currentPage++;
                    renderPagination();
                    showPage(currentPage);
                }
            });
            pagination.appendChild(nextItem);
        }

        // 显示指定页码的行
        function showPage(pageNumber) {
            const rows = tableBody.querySelectorAll('tr');
            const startIndex = (pageNumber - 1) * rowsPerPage;
            const endIndex = startIndex + rowsPerPage;

            rows.forEach((row, index) => {
                row.style.display = (index >= startIndex && index < endIndex) ? '' : 'none';
            });
        }
    </script>
</body>
</html>

三、关键功能说明

排序部分

  • 给需要排序的表头添加了sortable类,通过data-sort-index标记列的索引,方便JS识别排序目标列。
  • 点击表头时会切换排序方向(升序→降序→升序),同时更新箭头图标(用UIKit的chevron-up和chevron-down图标)。
  • 排序逻辑支持字符串、数字、日期三种类型的自动识别,确保不同数据类型都能正确排序。

分页部分

  • 使用UIKit的uk-pagination组件构建分页导航,通过JS动态生成页码按钮。
  • 每页显示行数可以通过rowsPerPage变量调整(示例中设为2)。
  • 切换页码时会自动计算需要显示的行范围,隐藏其他行,同时更新分页按钮的激活/禁用状态。

四、自定义调整建议

  • 如果不需要某列排序,只需要去掉该<th>的sortable类和data-sort-index属性即可。
  • 可以修改rowsPerPage变量来调整每页显示的行数。
  • 样式部分可以根据你的UI需求调整排序箭头的位置、颜色等。

内容的提问来源于stack exchange,提问作者rottenbanana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 00:07:50