本文分享了前端实现分页的案例,相关代码已经进行了注释
效果图
分页公式
起始: start:(页数-1) * 每页显示条数
终止: end:start + 每页显示条数
完整代码
<template>
<div class="main">
<div class="main_btn">
<button @click="btn(i + 1)" :class="{ btn: true, on: show == i + 1 }" v-for="(v, i) in arr" :key="v">{{ v
}}</button>
</div>
<div class="main_list">
<div @click="btnName(index)" :class="{ link_li: true, on: showF == index }" v-for="(item, index) in listArr"
:key="item.id">
<img class="img" :src="item.picUrl">
<p>{{ item.name }}</p>
</div>
</div>
<div class="main_paging">
<button @click="pre_page" class="paging_btn">上一页</button>
<ul class="list_ul">
<li @click="clickPage(i + 1)" :class="{ list_li: true, on: coupages == i + 1 }" v-for="(v, i) in listArr"
:key="v.id">
{{ i + 1 }}</li>
</ul>
<button @click="next_page" class="paging_btn">下一页</button>
</div>
</div>
</template>
<script setup>
import { reactive, onMounted, ref, computed } from "vue";
import axios from "axios";
let arr = reactive(['华语', '欧美', '韩国', '日本'])
// 数据存储 用于计算
let state = reactive({
arrlist: []
})
let show = ref(1) // 选项卡激活
let showF = ref() //歌手激活
// 每页条数
let pagesize = ref(10) //默认10
// 当前页数
let coupages = ref(1) //默认1
// 点击事件
let btn = (v) => {
// 将页数初始化为1
coupages.value = 1
show.value = v // 动态样式
// 请求数据
let filePath = `./${v}.txt`;
axios.get(filePath).then(res => {
state.arrlist = res.data
})
}
// 歌手激活
let btnName = (v) => {
showF.value = v
}
// 下一页
let next_page = () => {
// 判断页码是否等于计算后的数据长度 等于就说明后面没有数据了 也就不能到下一页了 直接return
if (coupages.value == listArr.value.length) return
// 不满足上面的条件就说明还有下一页 直接页码++
coupages.value++
}
// 上一页
let pre_page = () => {
// 判断当前页面是否等于1 等于1就说明已经在第一页了 也就不能到上一页了 直接return
if (coupages.value == 1) return
// 不满足上面的条件就说明还有上一页 直接页码--
coupages.value--
}
// 点击页码
let clickPage = (i) => {
// i 就是每个页码的下标 因为下标是从0开始的 而 页码起始值为1 所以在传下标的时候就对下标进行了+1的操作 然后将点击的页码传给coupages.value
// 因为coupages.value 值改变 计算属性会重新计算 返回新的数据
coupages.value = i
}
// 默认渲染
onMounted(() => {
btn(1);
});
// 计算返回截取后的数据
let listArr = computed(() => {
// start:(页数-1) * 每页显示条数
// end:start + 每页显示条数
let start = (coupages.value - 1) * pagesize.value //起始页
let end = start + pagesize.value // 最终页
return state.arrlist.slice(start, end) // 截取数据中的数据 返回
})
</script>
<style lang="scss" scoped>
.main {
width: 100%;
height: 100%;
padding: 20px;
display: flex;
flex-direction: column;
align-items: center;
.main_btn {
width: 80%;
height: 60px;
border-radius: 5px;
display: flex;
justify-content: space-evenly;
align-items: center;
.btn {
width: 120px;
height: 40px;
border: 0;
outline: none;
border-radius: 5px;
background-color: #f60;
color: #fff;
&.on {
background-color: #4f9fe9;
}
}
}
.main_list {
width: 80%;
display: flex;
flex-wrap: wrap;
justify-content: center;
margin: 10px 0;
.link_li {
width: 18%;
height: 200px;
display: flex;
flex-direction: column;
justify-content: space-between;
margin: 15px 0;
margin-right: auto;
box-shadow: 0 0 3px 0 #5f5e5e;
border-radius: 4px;
overflow: hidden;
&.on {
border: 2px solid #4f9fe9;
}
}
.img {
widows: 140px;
height: 140px;
}
p {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-bottom: 5px;
}
}
// 分页
.main_paging {
width: 80%;
height: 60px;
display: flex;
align-items: center;
.list_ul {
list-style: none;
margin: 0 30px;
height: 40px;
flex: 1;
display: flex;
align-items: center;
justify-content: center;
.list_li {
width: 25px;
height: 25px;
border-radius: 5px;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 0 3px #535252;
margin: 0 5px;
cursor: pointer;
&.on {
background-color: #4f9fe9;
color: #fff;
}
}
}
.paging_btn {
width: 120px;
height: 40px;
border: 0;
outline: none;
border-radius: 5px;
}
}
}
</style>