自适应网站会影响推广,广西住房和城乡建设厅继续教育网,设计本质是什么,网站建设的目标和需求目录 
一.问题背景 
二.代码讲解 
三.代码改装 
四.代码发布 今天我们来学习如何手写一个虚拟列表,本文将把虚拟列表进行拆分并讲解,然后发布到npm网站上. 
一.问题背景 
为什么需要虚拟列表呢?这是因为在面对大量数据的时候,我们的浏览器会将所有数据都渲染到表格上面,但是渲…目录 
一.问题背景 
二.代码讲解 
三.代码改装 
四.代码发布 今天我们来学习如何手写一个虚拟列表,本文将把虚拟列表进行拆分并讲解,然后发布到npm网站上. 
一.问题背景 
为什么需要虚拟列表呢?这是因为在面对大量数据的时候,我们的浏览器会将所有数据都渲染到表格上面,但是渲染极其消耗时间,就会出现浏览器卡顿的现象.总的来说就是机器性能不行,需要前端对体验进行优化. 
同时呢,我们其实正常人眼睛能看清的程度下,一个屏幕也就20-50行数据,面对10^4以上的数据的时候,如果为了只看这么点数据,而将所有数据都直接渲染,这会在短时间消耗大量的算力. 
我们前端对同样数据量的数据获取和数据渲染是两个过程,其中渲染的速度远慢于数据获取.所以我们采用虚拟列表这个技巧,每次计算视口可以容纳几个元素,让后将这些元素从总列表当中计算出来,只渲染这部分可视数据,就将压力分散到各段时间,很大程度上可以降低性能压力. 
二.代码讲解 
我最开始看的面经,作者是用的Vue2写的(不过我忘记出处了),代码如下: !-- /component/HelloWorld.vue --templatediv reflist classinfinite-list-container scrollscrollEvent($event)divclassinfinite-list-phantom:style{ height: listHeight  px }/divdiv classinfinite-list :style{ transform: getTransform }divrefitemsclassinfinite-list-itemv-foritem in visibleData:keyitem.id:style{ height: itemSize  px, lineHeight: itemSize  px }{{ item.value }}/div/div/div
/templatescript
export default {name: TheVirtualList,props: {//所有列表数据listData: {type: Array,default: ()  [],},//每项高度itemSize: {type: Number,default: 200,},},computed: {//列表总高度listHeight() {return this.listData.length * this.itemSize;},//可显示的列表项数visibleCount() {return Math.ceil(this.screenHeight / this.itemSize);},//偏移量对应的stylegetTransform() {return translate3d(0,${this.startOffset}px,0);},//获取真实显示列表数据visibleData() {return this.listData.slice(this.start,Math.min(this.end, this.listData.length));},},mounted() {this.screenHeight  this.$el.clientHeight;console.log(查看高度,this.screenHeight);this.start  0;this.end  this.start  this.visibleCount;// console.log(查看传入组件参数:,${this.itemSize});},data() {return {//可视区域高度screenHeight: 0,//偏移量startOffset: 0,//起始索引start: 0,//结束索引end: null,};},methods: {scrollEvent() {//当前滚动位置let scrollTop  this.$refs.list.scrollTop;//此时的开始索引this.start  Math.floor(scrollTop / this.itemSize);//此时的结束索引this.end  this.start  this.visibleCount;//此时的偏移量this.startOffset  scrollTop - (scrollTop % this.itemSize);console.log(查看滚动位置:,scrollTop);},},
};
/scriptstyle scoped
.infinite-list-container {height: 100%;overflow: auto;position: relative;-webkit-overflow-scrolling: touch;
}.infinite-list-phantom {position: absolute;left: 0;top: 0;right: 0;/* z-index: -1; */
}.infinite-list {left: 0;right: 0;top: 0;/* position: absolute; */text-align: center;
}.infinite-list-item {padding: 10px;color: #555;box-sizing: border-box;border-bottom: 1px solid #999;
}
/style 
这是一段Vue2代码,我来解释下其中的特殊之处 
this.$el.clientHeight; 
这段代码,代表获取当前组件的高度 
this.$refs.list.scrollTop; 
这串代码,代表获取ref值为list的容器的右侧滑动条距离顶部有多少px 
这里面用到的技巧就是,这个虚拟表格看起来是一个高度很高的容器,包裹着一个填满了数据的子容器,滑不完 
实际上该组件是一个高度很高的空容器一个只显示一个屏幕数据量的容器绝对定位进行布局 
实际效果如下: 三.代码改装 
由于现在都在写Vue,切是组合式,虽然框架兼容vue2写法,但是还是习惯Vue3组合式的写法 
不同的是,因为我们不能再用this.$el.clientHeight;来获取该组件的高度了,所以我在组件最外层又套了一个div,并打了一个ref,用其的高度来进行代替. 
代码如下: 
templatediv refvirtualList styleheight: 100%;div reflist classinfinite-list-container scrollhandleScroll()divclassinfinite-list-phantom:style{ height:  ${listHeight}px }/divdiv classinfinite-list :style{ transform: getTransform }divrefitemsclassinfinite-list-itemv-foritem in visibleData:keyitem.id:style{ height:  ${itemSize}px, lineHeight: ${itemSize}px }{{ item.value }}/div/div/div/div
/templatescript setup
import { onMounted } from vue;
import { computed } from vue;
import { defineProps ,ref} from vue;const props  defineProps({//所有列表数据listData: {type: Array,default: ()  [],},//每项高度itemSize: {type: Number,default: 200,},
})
const virtualList  ref(null);
const list  ref(null)
// 虚拟列表的数据结构
const virtualListInfo  ref({start: 0,end: null,startOffset: 0,
})
// 虚拟底板高度
const listHeight  computed(()  {return props.listData.length * props.itemSize
})
// 获取偏移
const getTransform  computed(()  {return translate3d(0,${virtualListInfo.value.startOffset}px,0);
})
// 一页渲染的元素个数
const visibleCount  computed(()  {return Math.ceil(virtualListInfo.value.screenHeight / props.itemSize);
})
// 要渲染的列表
const visibleData  computed(()  {// slice特性,如果第二个参数超过数组长度,那么直接获取到末尾即可return props.listData.slice(virtualListInfo.value.start,virtualListInfo.value.end)
})
const aaa  ref(1)
console.log(xxxxx,props,aaa);const handleScroll  () {if (list.value) {let scrollTop  list.value.scrollTop//此时的开始索引virtualListInfo.value.start  Math.floor(scrollTop / props.itemSize);//此时的结束索引virtualListInfo.value.end  virtualListInfo.value.start  visibleCount.value;//此时的偏移量virtualListInfo.value.startOffset  scrollTop - (scrollTop % props.itemSize);console.log(查看滚动位置:,scrollTop);} else {console.log(list未引用);}
}
onMounted(()  {virtualListInfo.value.screenHeight  virtualList.value.clientHeight;console.log(查看高度,virtualListInfo.value.screenHeight);virtualListInfo.value.start  0;virtualListInfo.value.end  virtualListInfo.value.start  visibleCount.value;// console.log(查看传入组件参数:,${this.itemSize});
})
/scriptstyle scoped
.infinite-list-container {height: 100%;overflow: auto;position: relative;-webkit-overflow-scrolling: touch;
}.infinite-list-phantom {position: absolute;left: 0;top: 0;right: 0;/* z-index: -1; */
}.infinite-list {left: 0;right: 0;top: 0;/* position: absolute; */text-align: center;
}.infinite-list-item {padding: 10px;color: #555;box-sizing: border-box;border-bottom: 1px solid #999;
}
/style四.代码发布 
我们封装好了这些组件,但是想要其他人发布,所以我们就需要将其放到公网上.像我们开发项目需要从仓库下载别人的包一样,我们也可以发布自己的包到npm仓库上 
你可以参考:如何发布自己的npm包超详细步骤博主都在用_npm 发布-CSDN博客 
我将上面的代码发布到我自己的仓库了,名称为:lqd-raw-component 欢迎下载尝试喵!