美文网首页
2023.15 虚拟列表实现

2023.15 虚拟列表实现

作者: wo不是黄蓉 | 来源:发表于2023-04-04 17:36 被阅读0次

虚拟列表实现思路

设置一个容器,用来计算可视区域大小

设置一个大容器,用来承载所有数据的高度和生成外部滚动条

设置一个展示数据的区域

设置开始展示数据的坐标,和结束展示数据的坐标,根据scrollTop计算出每次滑动后下次展示数据的开始坐标,根据scrollTop+可视区域大小计算出化冻后下次展示数据的结束坐标

编码使用vue3+element-plus,环境搭建,参考koa官网和element-plus官网

页面展示部分

<template>
  <h3>虚拟表格</h3>
  <!--容器部分-->
  <div class="table-container">
  <!--固定表头-->
    <table class="table-head" border>
      <thead>
        <tr>
          <th>Date</th>
          <th>Name</th>
          <th>Address</th>
        </tr>
        shixi
      </thead>
    </table>
    <!--滚动区域-->
    <div class="table-body" @scroll="handleScroll">
    <!--不可见区域,用来撑起滚动区域高度-->
      <table border class="scroll-table" height="100%">
        <tbody>
          <tr v-for="(item, index) in tableData" :key="index">
            <td>{{ item.date }}</td>
            <td>{{ item.name }}</td>
            <td>{{ item.address }}</td>
          </tr>
          <div class="bar"></div>
        </tbody>
      </table>
      <!--可视区域-->
      <table border class="scroll-table-show" height="100%">
        <tbody>
          <tr v-for="(item, index) in virtalTable" :key="index">
            <td>{{ item.date }}</td>
            <td>{{ item.name }}</td>
            <td>{{ item.address }}</td>
          </tr>
          <div class="bar"></div>
        </tbody>
      </table>
    </div>
  </div>
</template>
<style lang="scss">
html,
body {
  height: 500px;
}
.table-container {
  height: 500px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  .table-head {
    background-color: #e1f3d8;
  }
  .table-body {
    position: relative;
    flex: 1;
    background-color: #faecd8;
    overflow-y: auto;
  }
  .scroll-table {
    visibility: hidden;
  }
  .scroll-table-show {
    position: absolute;
    left: 0;
    right: 0;
  }
}
table {
  td,
  th {
    padding: 8px 0;
    border-color: #dcdfe6;
    border-width: 1px solid;
  }
  td:nth-child(2),
  th:nth-child(2),
  td:nth-child(1),
  th:nth-child(1) {
    width: 200px;
  }

  border-collapse: collapse;
  width: 100%;
}
</style>

js部分

<script lang="ts" setup>
import { table } from "console"
import { tr } from "element-plus/es/locale"
import { ref, onMounted, computed } from "vue"
//容器高度
let containerHeight = ref<number>(0)
//滑动高度
let scrollHeight = ref<number>(0)
//全部数据
let tableData = ref<Person[]>([])
//展示虚拟数据
let virtalTable = ref<Person[]>([])
//tr高度
let trHeight = ref<number>(0)
//可以容纳多少条数据
let showNum = computed(() => {
  return Math.ceil(containerHeight.value / trHeight.value)
})
//展示数据的开始下标
let start = ref<Number>(0)
//每次展示10条数据,展示数据的结束下标
let end = ref<Number>(10)

let top = ref<number>(0)
onMounted(() => {
  const ele = document.querySelector(".table-body")
  containerHeight.value = ele.offsetHeight
  const tr = document.querySelector("tr")
  trHeight.value = tr.offsetHeight

  const table = document.querySelector("tbody")
  scrollHeight.value = table.offsetHeight
  console.log(
    containerHeight.value,
    trHeight.value,
    showNum.value,
    scrollHeight.value
  )
//初始化加载函数
  renderData(start.value, end.value, tableData.value)
})

interface Person {
  date: string
  name: string
  address: string
}
//用来动态生成数据
generateTableData()
function generateTableData() {
  let data = []
  for (let index = 0; index < 2000; index++) {
    data.push({
      date: "2016-05-03",
      name: "Tom" + index,
      address: "No. 189, Grove St, Los Angeles",
    })
  }
  tableData.value = data
}

//处理滚动事件
function handleScroll(evt) {
  //获取滑动距离
  const scrollTop = document.querySelector(".table-body").scrollTop

  start.value = Math.ceil(scrollTop / trHeight.value)
  end.value = Math.ceil((scrollTop + containerHeight.value) / trHeight.value)
  // top.value = screenTop
  //将可视表格,的top改为滑动距离,或者不设置position,设置padding-top也是可以的
  document.querySelector(".scroll-table-show ").style.top = scrollTop + "px"

  renderData(start.value, end.value, tableData.value)
}

//加载表格数据
function renderData(start: number, end: number, tableData: Person[]) {
  virtalTable.value = tableData.slice(start, end)
  console.log(virtalTable.value)
}
</script>

完整代码

相关文章

网友评论

      本文标题:2023.15 虚拟列表实现

      本文链接:https://www.haomeiwen.com/subject/noysddtx.html