背景
1. 后台接口只是动态返回一个数组的数据,前端需要根据数据量的大小判断是否需要分页,页面高度固定
2. 页面根据页数大小有不同的展示
a. 只有一页 头部 + 内容 + 统计 + 尾部
b. 多页
i. 第一页 头部 + 内容 + 尾部
ii. 中间页 内容 + 尾部
iii. 最后一页 内容 + 统计 + 尾部
思路
1. 先判断是否一页能满足 如果能满足 不做数据处理
2. 不满足则肯定是多页
a. 先计算第一页的逻辑,将数组分为[第一页数据, 剩余数据]
b. 剩余数据只有两种情况
i. 符合尾页逻辑 直接将剩余数据放入最后一页
ii. 不符合尾页逻辑 递归实现中间页
页面情况
s1 只有一页 不需要操作
s2 多页
a. 第一页因为要显示头部 所以高度为 540 - 50
b. 中间页只显示内容 所以高度为 540
c. 尾页因为要显示统计 所以高度为 540 - 50
核心代码
<template>
<div class="container">
<div class="page" v-for="(list, index) in lists" :key="index">
<div class="top" v-if="index === 0">
<VHead />
</div>
<div class="middle">
<VTable :item="list" />
<VTotal v-if="index === lists.length - 1" />
</div>
<div class="bottom">
<VFooter />
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, nextTick } from 'vue'
import VHead from './components/VHead.vue'
import VTable from './components/VTable.vue'
import VTotal from './components/VTotal.vue'
import VFooter from './components/VFooter.vue'
import { init } from './data/index.js'
const HEIGHT = 540
const list = init(5)
const lists = ref([])
const render = async () => {
lists.value = [list]
await nextTick()
calculatePages()
}
const getTrs = () => {
const trEls = document.querySelectorAll('.v-table tbody tr')
let trHeights = []
for (let i = 0; i < trEls.length; i++) {
trHeights.push(trEls[i].offsetHeight)
}
const trHeightsTotal = trHeights.reduce((acc, cur) => acc + cur, 0)
return {
trHeights,
trHeightsTotal
}
}
const calculatePages = () => {
const isSiglePage = getIsSinglePage()
if (!isSiglePage) {
const remainIndex = calculateFirstPage()
lists.value = [list.slice(0, remainIndex)]
calculateOtherPages(remainIndex)
}
}
const getIsSinglePage = () => {
const { trHeightsTotal } = getTrs()
if (trHeightsTotal + 100 > HEIGHT) {
return false
}
return true
}
const calculateFirstPage = () => {
const { trHeights } = getTrs()
const maxHeight = HEIGHT - 50
let total = 0
let index = 0
for (let i = 0; i < trHeights.length; i++) {
if (total + trHeights[i] > maxHeight) {
break
}
total += trHeights[i]
index = i
}
return index
}
const calculateOtherPages = (remainIndex) => {
const { trHeights } = getTrs()
const remainTrHeights = trHeights.slice(remainIndex)
const remainTrTotal = remainTrHeights.reduce((acc, cur) => acc + cur, 0)
if (remainTrTotal + 50 > HEIGHT) {
let total = 0
let index = 0
for (let i = remainIndex; i < trHeights.length; i++) {
if (total + trHeights[i] > HEIGHT) {
break
}
total += trHeights[i]
index = i
}
if (index) {
lists.value.push(list.slice(remainIndex, index))
calculateOtherPages(index)
}
} else {
lists.value.push(list.slice(remainIndex))
}
}
onMounted(() => {
render()
})
</script>
<style lang="scss" scoped>
.container {
display: flex;
flex-direction: column;
}
.page {
width: 800px;
height: 590px;
border: 1px solid #ccc;
display: flex;
flex-direction: column;
justify-content: space-between;
margin-bottom: 2px;
overflow: hidden;
.top,
.bottom {
height: 50px;
}
.middle {
flex: 1;
overflow: hidden;
}
}
</style>
小结
最开始想的是通过AI实现,经过多次测试发现AI实现的有很多缺陷,甚至需求都不明白,最后只能自己一步一步实现,想了很多方案,最终在此方案下符合需求。
如果有更好的方案,欢迎交流
效果