sticky-rows.vue 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. <template>
  2. <el-table-v2
  3. :columns="columns"
  4. :data="tableData"
  5. :fixed-data="fixedData"
  6. :width="700"
  7. :height="400"
  8. :row-class="rowClass"
  9. fixed
  10. @scroll="onScroll"
  11. />
  12. </template>
  13. <script lang="ts" setup>
  14. import { computed, ref } from 'vue'
  15. const generateColumns = (length = 10, prefix = 'column-', props?: any) =>
  16. Array.from({ length }).map((_, columnIndex) => ({
  17. ...props,
  18. key: `${prefix}${columnIndex}`,
  19. dataKey: `${prefix}${columnIndex}`,
  20. title: `Column ${columnIndex}`,
  21. width: 150,
  22. }))
  23. const generateData = (
  24. columns: ReturnType<typeof generateColumns>,
  25. length = 200,
  26. prefix = 'row-'
  27. ) =>
  28. Array.from({ length }).map((_, rowIndex) => {
  29. return columns.reduce(
  30. (rowData, column, columnIndex) => {
  31. rowData[column.dataKey] = `Row ${rowIndex} - Col ${columnIndex}`
  32. return rowData
  33. },
  34. {
  35. id: `${prefix}${rowIndex}`,
  36. parentId: null,
  37. }
  38. )
  39. })
  40. const columns = generateColumns(10)
  41. const data = generateData(columns, 200)
  42. const rowClass = ({ rowIndex }) => {
  43. if (rowIndex < 0 || (rowIndex + 1) % 5 === 0) return 'sticky-row'
  44. }
  45. const stickyIndex = ref(0)
  46. const fixedData = computed(() =>
  47. data.slice(stickyIndex.value, stickyIndex.value + 1)
  48. )
  49. const tableData = computed(() => {
  50. return data.slice(1)
  51. })
  52. const onScroll = ({ scrollTop }) => {
  53. stickyIndex.value = Math.floor(scrollTop / 250) * 5
  54. }
  55. </script>
  56. <style>
  57. .el-el-table-v2__fixed-header-row {
  58. background-color: var(--el-color-primary-light-5);
  59. font-weight: bold;
  60. }
  61. </style>