页面优化——加载海量数据
Document
that stores a segment of a document structure comprised of nodes just like a standard document. The key difference is that because the document fragment isn't part of the active document tree structure, changes made to the fragment don't affect the document, cause reflow, or incur any performance impact that can occur when changes are made.requestAniminationFrame
The window.requestAnimationFrame() method tells the browser that you wish to perform an animation and requests that the browser call a specified function to update an animation before the next repaint. The method takes a callback as an argument to be invoked before the repaint.
------JAVASCRIPT MDN
方法一:今天在知乎上看到了 这篇 文章。
脱离文章,口述:
为了避免dom操作造成的回流和重绘,渲染时,先创建一个DocumentFragment,里边放置可视区域应有的条数,塞到容器里,先渲染;余下的数据在下一帧前重复上一次的操作,直到数据渲染完。requestAnimationFrame是页面重绘前自动触发的window自带函数。
主要就两点:
- DocumentFragment不会引发文档树重绘和回流
- requestAnimationFrame当前帧之前操作DOM,操作完成后渲染。
其中requestAnimationFrame,浏览器新一帧渲染前预知执行方法---666
requestIdleCallback
只有当前帧的运行时间小于16.66ms时,函数fn才会执行。否则,就推迟到下一帧,如果下一帧也没有空闲时间,就推迟到下下一帧,以此类推。
前端页面渲染是逐帧的----第一次是从andriod同事那里听到的,因为他看到我写的H5页面上的图“一排一排”的显示。
它还可以接受第二个参数,表示指定的毫秒数。如果在指定 的这段时间之内,每一帧都没有空闲时间,那么函数fn将会强制执行。
requestIdleCallback(fn, 5000);
requestIdleCallback其他内容附上 链接 。
这个方法缺点,渲染的多了还是会卡顿。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
方法二:可视区域内显示数据,非可视区域不显示。
布局为:外框1固定高度,内容超出滚动;内置外框2高度与显示的数据高度相同;内置外框3包裹显示的数据;外框2设置相对定位,外框3设置绝对定位;
操作:页面向上滚动时,仍然要在当前区域显示数据,外框3设置top与offsetTop相同:外框2在向上滚动,外框3相对外框2向下定位移动
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> <style> * { margin: 0; padding: 0; } .scroll { height: 100vh; overflow-y: auto; } </style> <script src="vue.global.js"></script> </head> <body> <div id="app"> <div ref="scroll" class="scroll" @scroll="handleScroll"> <div :style="{'height':`${itemHeight*diff}px`,'position':'relative'}" > <div :style="{'position':'absolute','top':`${scrollTop}px`}"> <div v-for="item in showList" ::key="item" :style="{'height': `${itemHeight}px`}" > {{item}} </div> </div> </div> </div> </div> <script> const {createApp} = Vue; createApp({ data() { return { lists: [], startIndex: 0, diff: 20, itemHeight: 50, contentHeight: 0, scrollTop: 0, }; }, computed: { showList() { return this.lists.slice( this.startIndex, this.startIndex + this.diff ); }, }, mounted() { this.lists = Array.from(Array(50)).map((_, i) => i); this.contentHeight = document.querySelector(".scroll").clientHeight; this.diff = Math.ceil(this.contentHeight / this.itemHeight); this.startIndex = Math.floor(this.scrollTop / this.itemHeight); this.showList = this.lists.slice( this.startIndex, this.startIndex + this.diff ); }, methods: { handleScroll(e) { this.scrollTop = this.$refs.scroll.scrollTop; this.startIndex = Math.floor(this.scrollTop / this.itemHeight); }, }, }).mount("#app"); </script> </body> </html>
实用方法:
1.例如VUE项目中,异步获取的数据可以设置Object.freeze(res.data),减少VUE数据代理开销;
2.在返回拦截器中解构出页面真实使用的数据;