1. template>
  2. <div :style="{height: `${contentHeight}px`}" class="content_box" @scroll="scroll">
  3. <!--这层div是为了把高度撑开,让滚动条出现,height值为所有数据总高-->
  4. <div :style="{'height': `${itemHeight*(listAll.length)}px`, 'position': 'relative'}">
  5. <!--可视区域里所有数据的渲染区域-->
  6. <div :style="{'position': 'absolute', 'top': `${top}px`}">
  7. <!--单条数据渲染区域-->
  8. <div v-for="(item,index) in showList" :key="index" class="item">
  9. {{item}}
  10. </div>
  11. </div>
  12. </div>
  13. </div>
  14. </template>
  15. <script>
  16. export default {
  17. name: "list",
  18. data(){
  19. return{
  20. listAll: [], //所有数据
  21. showList: [], //可视区域显示的数据
  22. contentHeight: 500, //可视区域高度
  23. itemHeight: 30, //每条数据所占高度
  24. showNum: 0, //可是区域显示的最大条数
  25. top: 0, //偏移量
  26. scrollTop: 0, //卷起的高度
  27. startIndex: 0, //可视区域第一条数据的索引
  28. endIndex: 0, //可视区域最后一条数据后面那条数据的的索引,因为后面要用slice(start,end)方法取需要的数据,但是slice规定end对应数据不包含在里面
  29. }
  30. },
  31. methods:{
  32. //构造10万条数据
  33. getList(){
  34. for(let i=0;i<100000;i++){
  35. this.listAll.push(`我是第${i}条数据呀`)
  36. }
  37. },
  38. //计算可视区域数据
  39. getShowList(){
  40. this.showNum = Math.ceil(this.contentHeight/this.itemHeight); //可视区域最多出现的数据条数,值是小数的话往上取整,因为极端情况是第一条和最后一条都只显示一部分
  41. this.startIndex = Math.floor(this.scrollTop/this.itemHeight); //可视区域第一条数据的索引
  42. this.endIndex = this.startIndex + this.showNum; //可视区域最后一条数据的后面那条数据的索引
  43. this.showList = this.listAll.slice(this.startIndex, this.endIndex) //可视区域显示的数据,即最后要渲染的数据。实际的数据索引是从this.startIndex到this.endIndex-1
  44. const offsetY = this.scrollTop - (this.scrollTop % this.itemHeight); //在这需要获得一个可以被itemHeight整除的数来作为item的偏移量,这样随机滑动时第一条数据都是完整显示的
  45. this.top = offsetY;
  46. },
  47. //监听滚动事件,实时计算scrollTop
  48. scroll(){
  49. this.scrollTop = document.querySelector('.content_box').scrollTop; //element.scrollTop方法可以获取到卷起的高度
  50. this.getShowList();
  51. }
  52. },
  53. mounted() {
  54. this.getList();
  55. this.scroll();
  56. }
  57. }
  58. </script>
  59. <style scoped>
  60. .content_box{
  61. overflow: auto; /*只有这行代码写了,内容超出高度才会出现滚动条*/
  62. width: 700px;
  63. border: 1px solid red;
  64. }
  65. /*每条数据的样式*/
  66. .item{
  67. height:30px;
  68. padding: 5px;
  69. color: #666;
  70. box-sizing: border-box;
  71. }
  72. </style>

解释“为啥上面使用了定位 ”给了偏移量top

因为 下拉滚动条后,之前显示的东西就会被拉到上面的外面,隐藏掉,同时滚动条下拉的时候,只会显示下拉到
的位置的数据,这个时候,就需要使用偏移量top 想当于把它定位到最上面显示