文章目錄
- 背景
- 思路
- 頁面情況
- 核心代碼
- 小結
- 效果
背景
1. 后臺接口只是動態返回一個數組的數據,前端需要根據數據量的大小判斷是否需要分頁,頁面高度固定2. 頁面根據頁數大小有不同的展示a. 只有一頁 頭部 + 內容 + 統計 + 尾部b. 多頁i. 第一頁 頭部 + 內容 + 尾部ii. 中間頁 內容 + 尾部iii. 最后一頁 內容 + 統計 + 尾部
思路
1. 先判斷是否一頁能滿足 如果能滿足 不做數據處理2. 不滿足則肯定是多頁a. 先計算第一頁的邏輯,將數組分為[第一頁數據, 剩余數據]b. 剩余數據只有兩種情況i. 符合尾頁邏輯 直接將剩余數據放入最后一頁ii. 不符合尾頁邏輯 遞歸實現中間頁
頁面情況
s1 只有一頁 不需要操作s2 多頁a. 第一頁因為要顯示頭部 所以高度為 540 - 50b. 中間頁只顯示內容 所以高度為 540c. 尾頁因為要顯示統計 所以高度為 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 = 540const 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 - 50let total = 0let index = 0for (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 = 0let index = 0for (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實現的有很多缺陷,甚至需求都不明白,最后只能自己一步一步實現,想了很多方案,最終在此方案下符合需求。
如果有更好的方案,歡迎交流
效果
完整代碼