购物车页面,通过计算当前可视区域的商品和高度,用虚拟列表的方式只渲染可视区域内的数据
一个商品选项的高度
可视区域高度
展示商品的数量等于可视区域高度/一个商品选项的高度
滑动条距离顶部的距离
this.$el.clienHeight 水平滚动条的高度 (如果存在) ,不然就是屏幕高度

虚拟列表作用
只渲染出可视区域内的数据

讲一讲实现实现过程

首先通过给元素添加ref,.clientHeight获得可视区域高度,再设置列表每项高度,获得当前页面可展示多少项
监听onScroll事件触发时,通过ref获取滚动离顶部的距离scrolltop,
改变开始项和结束项从全部列表取数据到页面上进行渲染
监听虚拟列表滚动更换可视区内容

  1. <template>
  2. <div id="app">
  3. <!-- 包裹可视区域的可滚动的虚拟列表 -->
  4. <div class="fictitious" @scroll="onScroll($event)" ref="ftwh" >
  5. <!-- 占位元素,高度为总列表高度,提供滚动条,通过绝对定位脱离普通文档流不占父元素高度 -->
  6. <div :style="{height: phantomHeight+'px'}" class="seize"></div>
  7. <!-- 可视区域 -->
  8. <div class="LookCant" :style="{transform: getTransform}">
  9. <p v-for="item of lookArr" :key="item" :style="{height: rowHeight +'px'}" class="pp">
  10. {{item}}
  11. </p>
  12. </div>
  13. </div>
  14. </div>
  15. </template>
  16. <script>
  17. export default {
  18. data(){
  19. return {
  20. //总列表数据
  21. arr:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99],
  22. //可视高度
  23. height: 0,
  24. //列表元素高度
  25. rowHeight: 100,
  26. //开始索引
  27. starItem:0,
  28. //结束索引
  29. endItem:0,
  30. //滑动条离顶部距离
  31. startOffset:0
  32. }
  33. },
  34. methods: {
  35. onScroll(){
  36. if((this.$refs.ftwh.scrollTop/this.rowHeight+this.limit)>this.total){
  37. this.endItem = this.total
  38. return false
  39. }
  40. this.startOffset = this.$refs.ftwh.scrollTop
  41. this.starItem = Math.floor(this.startOffset/this.rowHeight);
  42. this.endItem = this.starItem+this.limit;
  43. console.log(this.lookArr);
  44. console.log(this.startOffset);
  45. }
  46. },
  47. computed:{
  48. // 总条数
  49. total(){
  50. return this.arr.length;
  51. },
  52. //列表总高度
  53. phantomHeight(){
  54. return this.arr.length*this.rowHeight;
  55. },
  56. //可视范围内可展示元素数量
  57. limit(){
  58. return Math.ceil(this.height/this.rowHeight)
  59. },
  60. //真实显示的列表数据
  61. lookArr(){
  62. return this.arr.slice(this.starItem,Math.min(this.arr.length,this.endItem));
  63. },
  64. getTransform(){
  65. return `translate(0,${this.startOffset}px)`;
  66. }
  67. },
  68. mounted() {
  69. this.height = this.$el.clientHeight;
  70. this.starItem = 0;
  71. this.endItem = this.starItem+this.limit;
  72. },
  73. }
  74. </script>
  75. <style>
  76. html{
  77. height: 100%;
  78. }
  79. body{
  80. margin: 0;
  81. padding: 0;
  82. height: 100%;
  83. }
  84. #app{
  85. height: 100%;
  86. }
  87. .fictitious{
  88. height: 100%;
  89. position: relative;
  90. overflow-y:auto;
  91. }
  92. .pp{
  93. box-sizing: border-box;
  94. padding: 10px 0;
  95. text-align: center;
  96. background-color: #999;
  97. margin: 0;
  98. border-bottom: 1px solid #fff;
  99. line-height: 100px;
  100. }
  101. .seize{
  102. z-index: -1;
  103. position: absolute;
  104. top: 0;
  105. left: 0;
  106. right: 0;
  107. }
  108. </style>