bootstrap 分页

61 阅读1分钟
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue and Bootstrap Table with Search</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
    <style>
        .scrollable-table-container {
            overflow-y: auto;
            max-height: 300px;
        }
        .table-fixed {
            width: 100%;
            table-layout: fixed;
            border-collapse: separate;
        }
        .table-fixed thead th {
            position: sticky;
            top: 0;
            background-color: #fff;
            z-index: 1;
        }
        .table-fixed th, .table-fixed td {
            padding: 8px;
            text-align: left;
            border-bottom: 1px solid #ddd;
            white-space: nowrap;
        }
        .table-fixed tbody td {
            overflow-x: auto;
            white-space: nowrap;
        }
        .scrollable-cell {
            overflow-x: auto;
            white-space: nowrap;
            scrollbar-width: none;
            -ms-overflow-style: none;
        }
        .scrollable-cell::-webkit-scrollbar {
            display: none;
        }
        .table-fixed tbody td {
            margin-right: 5px;
            margin-left: 5px; 
        }
    </style>
</head>
<body>
<div id="app" class="container">
    <div class="form-group">
        <input type="text" class="form-control" placeholder="Search" v-model="searchQuery" @input="filterItems">
    </div>
    <div class="scrollable-table-container">
        <table class="table table-fixed">
            <thead>
                <tr>
                    <th>Name</th>
                </tr>
            </thead>
            <tbody>
                <tr v-for="item in paginatedItems" :key="item.id">
                    <td class="scrollable-cell">{{ item.name }}</td>
                </tr>
            </tbody>
        </table>
    </div>
    <!-- 分页组件 -->
    <nav>
        <ul class="pagination">
            <li :class="{ 'disabled': currentPage === 1 }">
                <a href="#" @click.prevent="changePage(currentPage - 1)" aria-label="Previous">
                    <span aria-hidden="true">&laquo;</span>
                </a>
            </li>
            <li v-for="page in totalPages" :class="{ 'active': page === currentPage }">
                <a href="#" @click.prevent="changePage(page)">{{ page }}</a>
            </li>
            <li :class="{ 'disabled': currentPage === totalPages }">
                <a href="#" @click.prevent="changePage(currentPage + 1)" aria-label="Next">
                    <span aria-hidden="true">&raquo;</span>
                </a>
            </li>
        </ul>
    </nav>
</div>

<!-- 引入Vue JS -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 引入Bootstrap的JS库 -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.4.0/axios.min.js"></script>
<script>
    new Vue({
        el: '#app',
        data: {
            items: [],
            filteredItems: [],
            searchQuery: '',
            currentPage: 1,
            pageSize: 5,
        },
        computed: {
            totalPages() {
                return Math.ceil(this.filteredItems.length / this.pageSize);
            },
            paginatedItems() {
                const start = (this.currentPage - 1) * this.pageSize;
                const end = start + this.pageSize;
                return this.filteredItems.slice(start, end);
            }
        },
        created() {
            this.getData();
            const savedPage = this.getCookie('currentPage');
            if (savedPage) {
                this.currentPage = parseInt(savedPage, 10);
            }
        },
        methods: {
            getData() {
                fetch('http://localhost:3000/data')
                    .then(response => {
                        if (!response.ok) {
                            throw new Error('Network response was not ok ' + response.statusText);
                        }
                        return response.json();
                    })
                    .then(data => {
                        this.items = data.data;
                        this.filteredItems = this.items;
                    })
                    .catch(error => {
                        console.error('There has been a problem with your fetch operation:', error);
                    });
            },
            changePage(page) {
                if (page > 0 && page <= this.totalPages) {
                    this.currentPage = page;
                    this.setCookie('currentPage', page, 7); // 设置cookie,有效期7天
                }
            },
            setCookie(name, value, days) {
                const d = new Date();
                d.setTime(d.getTime() + (days * 24 * 60 * 60 * 1000));
                const expires = "expires=" + d.toUTCString();
                document.cookie = name + "=" + value + ";" + expires + ";path=/";
            },
            getCookie(name) {
                const nameEQ = name + "=";
                const ca = document.cookie.split(';');
                for(let i = 0; i < ca.length; i++) {
                    let c = ca[i];
                    while (c.charAt(0) == ' ') c = c.substring(1, c.length);
                    if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
                }
                return null;
            },
            filterItems() {
                this.currentPage = 1;
                const query = this.searchQuery.toLowerCase();
                this.filteredItems = this.items.filter(item => item.name.toLowerCase().includes(query));
            }
        }
    });
</script>
</body>
</html>