vue3.2 前端动态分页算法

文章目录

背景

javascript 复制代码
   1. 后台接口只是动态返回一个数组的数据,前端需要根据数据量的大小判断是否需要分页,页面高度固定
   2. 页面根据页数大小有不同的展示
     a. 只有一页  头部 + 内容 + 统计 + 尾部
     b. 多页
        i.  第一页 头部 + 内容 + 尾部
        ii. 中间页 内容 + 尾部
        iii. 最后一页 内容 + 统计 + 尾部

思路

javascript 复制代码
	1. 先判断是否一页能满足 如果能满足 不做数据处理
	2. 不满足则肯定是多页
	    a. 先计算第一页的逻辑,将数组分为[第一页数据, 剩余数据]
	    b. 剩余数据只有两种情况
	      i. 符合尾页逻辑 直接将剩余数据放入最后一页
	     ii. 不符合尾页逻辑 递归实现中间页

页面情况

javascript 复制代码
 s1 只有一页  不需要操作
 
 s2 多页
    a. 第一页因为要显示头部  所以高度为  540 - 50
    b. 中间页只显示内容      所以高度为  540
    c. 尾页因为要显示统计    所以高度为  540 - 50

核心代码

javascript 复制代码
<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实现的有很多缺陷,甚至需求都不明白,最后只能自己一步一步实现,想了很多方案,最终在此方案下符合需求。

如果有更好的方案,欢迎交流

效果


完整代码

相关推荐
阳光是sunny3 分钟前
走进AI(1):细说RAG、MCP、Agent、Function Call
前端·ai编程
剪刀石头布啊12 分钟前
var、let、const与闭包、垃圾回收
前端·javascript
剪刀石头布啊13 分钟前
js常见的单例
前端·javascript
剪刀石头布啊14 分钟前
数据口径
前端·后端·程序员
剪刀石头布啊18 分钟前
http状态码大全
前端·后端·程序员
剪刀石头布啊20 分钟前
iframe通信、跨标签通信的常见方案
前端·javascript·html
Tisfy23 分钟前
LeetCode 2411.按位或最大的最小子数组长度:一次倒序遍历
数据结构·算法·leetcode·题解·位运算·遍历
宇之广曜29 分钟前
搭建 Mock 服务,实现前端自调
前端·mock
yuko093130 分钟前
【手机验证码】+86垂直居中的有趣问题
前端
用户15129054522034 分钟前
Springboot中前端向后端传递数据的几种方式
前端