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

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

效果


完整代码

相关推荐
撰卢1 分钟前
总结一下vue3的组件之间数据转递,子组件传父组件,父组件传子组件
前端·javascript·vue.js
野生的编程萌新36 分钟前
【数据结构】从基础到实战:全面解析归并排序与计数排序
数据结构·算法·排序算法
前端开发爱好者40 分钟前
Vue3 超强“积木”组件!5 分钟搞定可交互 3D 机房蓝图!
前端·javascript·vue.js
Mercury_Lc43 分钟前
【链表 - LeetCode】206. 反转链表【带ACM调试】
算法·链表
前端开发爱好者44 分钟前
尤雨溪力荐!Vue3 专属!100+ 动效组件!
前端·javascript·vue.js
前端开发爱好者1 小时前
尤雨溪力荐!Vue3 生态最强大的 14 个 UI 组件库!
前端·javascript·vue.js
lb29171 小时前
关于多个el-input的自动聚焦,每输入完一个el-input,自动聚焦到下一个
前端·javascript·vue.js
sorryhc1 小时前
【AI解读源码系列】ant design mobile——Divider分割线
前端·javascript·react.js
YuTaoShao2 小时前
【LeetCode 热题 100】152. 乘积最大子数组——(解法一)递推
java·算法·leetcode·职场和发展
前端进阶者2 小时前
electron-vite_20配置依赖包运行时区外部加载commonjsExternals_vite-plugin-commonjs-externals
前端·electron