<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>如何渲染几万条数据并不卡住界面</title> </head> <body> <ul>控件</ul> <script> setTimeout(() => { // 插入十万条数据 const total = 100000 // 一次插入 20 条,如果觉得性能不好就减少 const once = 20 // 渲染数据总共需要几次 const loopCount = total / once let countOfRender = 0 let ul = document.querySelector("ul"); function add() { // 优化性能,插入不会造成回流 const fragment = document.createDocumentFragment(); for (let i = 0; i < once; i++) { const li = document.createElement("li"); li.innerText = Math.floor(Math.random() * total); fragment.appendChild(li); } ul.appendChild(fragment); countOfRender += 1; loop(); } function loop() { if (countOfRender < loopCount) { window.requestAnimationFrame(add); } } loop(); }, 0); </script> </body> </html> 提示:你可以先修改部分代码再运行。 https://juejin.cn/post/7252684645979111461 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script> <title>虚拟列表</title> <style> .v-scroll { height: 600px; width: 400px; border: 3px solid #000; overflow: auto; position: relative; -webkit-overflow-scrolling: touch; } .infinite-list { position: absolute; left: 0; top: 0; right: 0; z-index: -1; } .scroll-list { left: 0; right: 0; top: 0; position: absolute; text-align: center; } .scroll-item { padding: 10px; color: #555; box-sizing: border-box; border-bottom: 1px solid #999; } </style> </head> <body> <div id="app"> <div ref="list" class="v-scroll" @scroll="scrollEvent($event)"> <div class="infinite-list" :style="{ height: listHeight + 'px' }"></div> <div class="scroll-list" :style="{ transform: getTransform }"> <div ref="items" class="scroll-item" v-for="item in visibleData" :key="item.id" :style="{ height: itemHeight + 'px',lineHeight: itemHeight + 'px' }">{{ item.msg }}</div> </div> </div> </div> <script> var throttle = (func, delay) => { //节流 var prev = Date.now(); return function () { var context = this; var args = arguments; var now = Date.now(); if (now - prev >= delay) { func.apply(context, args); prev = Date.now(); } } } let listData = [] for (let i = 1; i <= 10000; i++) { listData.push({ id: i, msg: i + ':' + Math.floor(Math.random() * 10000) }) } const { createApp } = Vue createApp({ data() { return { listData: listData, itemHeight: 60, //可视区域高度 screenHeight: 600, //偏移量 startOffset: 0, //起始索引 start: 0, //结束索引 end: null, }; }, computed: { //列表总高度 listHeight() { return this.listData.length * this.itemHeight; }, //可显示的列表项数 visibleCount() { return Math.ceil(this.screenHeight / this.itemHeight) }, //偏移量对应的style getTransform() { return <code>translate3d(0,${this.startOffset}px,0)</code>; }, //获取真实显示列表数据 visibleData() { return this.listData.slice(this.start, Math.min(this.end, this.listData.length)); } }, mounted() { this.start = 0; this.end = this.start + this.visibleCount; }, methods: { scrollEvent() { //当前滚动位置 let scrollTop = this.$refs.list.scrollTop; //此时的开始索引 this.start = Math.floor(scrollTop / this.itemHeight); //此时的结束索引 this.end = this.start + this.visibleCount; //此时的偏移量 this.startOffset = scrollTop - (scrollTop % this.itemHeight); } } }).mount('#app') </script> </body> </html> 提示:你可以先修改部分代码再运行。 转载请注明:有爱前端 » 如何渲染几万条数据并不卡住界面 喜欢 (0)or分享 (0)