vue 虚拟列表 渲染大量数据

如果后端一次返回数据量较大,而且要用列表的形式展现给用户,如果我们不做处理的话,在浏览器中渲染大量 dom节点,是极其耗费时间的

vue 虚拟列表 渲染大量数据_第1张图片

<template>
 <div class="list_view" @scroll="handleScroll">
  <div class="scroll_area" :style="{ height: scrollAreaHeight }">div>
  <div ref="content" class="list_view_content">
   <div
    class="list_view_item"
    :style="{ height: itemHeight + 'px' }"
    v-for="(item,index) in showList"
    :key="index"
   >
    <div class="box_itme">
     <div class="itme_img">{{ item.img }}div>
     <div  class="itme_name">{{ item.name }}div>
    div>
   div>
  div>
 div>
template>

<script>
export default {
 name: 'ListView',
 props: {
  list:{
   type: Array,
   default: ()=>[]
  },
  itemHeight: {
   type: Number,
   default: 30
  }
 },
 data() {
  return {
   
   showNum: 20,//显示几条数据
   start: 0,//滚动过程显示的开始索引
   end: 20,//滚动过程显示的结束索引
  };
 },

 computed: {
  //内容总高度
  scrollAreaHeight() {
   return this.list.length * this.itemHeight + 'px';
  },
  //区可视的数据, 
  showList() {
   return this.list.slice(this.start, this.end); 
  }
 },
 mounted() {
  this.computescrollArea();
  window.addEventListener('resize',()=>{//窗口改变时
   this.$nextTick(()=>{ 
   this.handleScroll()
   }) 
  })
 },
 methods: {
  //计算滚动
  computescrollArea(scrollTop) {
   scrollTop = scrollTop || 0;  

   this.showNum = Math.ceil(this.$el.clientHeight / this.itemHeight); // 取得可见区域的可见列表项数量
    //开始的数组索引     滚到第几条数据  =  滚动高度   /  每个item的高度 
    this.start = Math.floor(scrollTop / this.itemHeight); 
    //结束索引    可视的数据 = 滚到第几条数据  + 显示几条数据
    this.end = this.start + this.showNum; 
    //绝对定位对相对定位的偏移量   已滚动的高度 = 滚到第几条数据  * 每个item的高度 
   this.$refs.content.style.webkitTransform = `translate3d(0, ${this.start * this.itemHeight}px, 0)`; 
   // this.$refs.content.style.webkitTransform = `translateY(${start * this.itemHeight}px)`;  
  },
  //滚动触发
  handleScroll() {
    //获取已滚动的高度
   const scrollTop = this.$el.scrollTop;
   this.computescrollArea(scrollTop);
  }
 }
}
script>

<style>
.list_view {
 width: 500px;
 margin: 0 auto;
 height: calc(100vh - 100px);
 overflow: auto;
 position: relative;
 border: 1px solid #aaa;
}

.scroll_area {
 position: absolute;
 left: 0;
 top: 0;
 right: 0;
 z-index: -1;
}

.list_view_content {
 scroll-behavior: smooth;/*滚动平滑属性*/
 left: 0;
 right: 0;
 top: 0;
 position: absolute;
}

.list_view_item {
 padding: 5px;
 color: #666;
 height: 50px;
 box-sizing: border-box;
 margin-bottom: 10px;

}
.box_itme{
 width: 100%;
 height: 100%;

 display: flex;
 align-items: center;

}
.box_itme >div{
 height: 100%;

 display: flex;
 align-items: center;
 justify-content: center;

}
.itme_img{

 background-color: #eee;
 flex: 0.3;

}
.itme_name{
 background-color: #f8f8f8;
 flex: 0.7;
}
style>


使用

 
<template>
  <div id="home">
    <xn2 :list="list" :itemHeight="100">xn2>
  div>
template>
<script>
import xn2 from "../components/xn2.vue";

export default {
  components: {
    xn2
  },
  data() {
    return {
      list:[],
    };
  },
  created() {
    for (let index = 0; index < 100000; index++) {
      this.list.push({
        id: index,
        name: '第' + index + '个',
        img: 'url' + index,
      })

    }
  },
};
script>

你可能感兴趣的:(vue.js,javascript,前端)