<!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">«</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">»</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>