15.如何对超大量数据进行渲染

1. 优化方向

  1. 分批渲染DOM:避免一次性渲染大量DOM,以减轻浏览器性能压力
  2. 集中DOM操作:将DOM操作集中在一起执行,减少不必要的渲染
  3. 移除非可视区域DOM:将不在可视区域的DOM元素移除,减少内存占用和渲染负担

2. 实现大量数据渲染的方法

2.1 使用定时器分批渲染

通过setInterval定时器分批插入元素,每次处理一定数量的节点

export default (element, data) => {
	const fragment = document.createDocumentFragment()
	let timer = setInterval(() => {
		for (let i = 0; i < 20; i++) {
			const item=data.shift()
			if(!item){
				clearInterval(timer)
				break
			}
			const div=document.createElement('div')
			fragment.appendChild(div)
			// 设置div属性和样式
		}
		element.appendChild(fragment)
	})
}

2.2 使用requestAnimationFrame代替定时器

使用requestAnimationFrame来替代setInterval,它会在浏览器下一次重绘之前执行回调函数

export default (element, data) => {
	requestAnimationFrame(() => stop(element, data))

	const stop = (element, data) => {
		const fragment = document.createDocumentFragment()
		for (let i = 0; i < 20; i++) {
			const item = data.shift()
			if (!item) {
				break
			}
		}
		const div = document.createElement('div')
		fragment.appendChild(div)
	}
	element.appendChild(fragment)
	data.length && requestAnimationFrame(() => stop(element, data))
}

2.3 使用虚拟滚动

仅渲染可视区域的数据,随着用户的滚动,动态添加或删除DOM节点

  • 实现过程
    • 设置父节点position:relative子节点position:absolute,并通过transform定位
    • 使用boundary数组管理渲染区域的上下边界
    • 使用startIndex和endIndex标记需要渲染的数据范围
    • 定义step变量控制每次添加或删除的节点数量
    • 设置threshold阈值用于触发添加或删除事件
export default (element,data)=>{
	const boundary=[0,0]
	let startIndex=0
	let endIndex=0
	const step=10
	const threshold=200
	// 初始化和事件绑定了
	const createElement=(item,mode)=>{
		const div=document.createElement('div')
		// 设置属性和样式
		return div
	}
	
	const initScroll=(element)=>{
		element.addEventListener('scroll',scroll(element,(e)=>{
			// 根据滚动事件添加或删除DOM节点
		})
	}
}
// 其他辅助函数

虚拟滚动的关键点:

  • 使用transform而非top等属性设置子节点位置,以避免触发重排和重绘
  • 通过监听滚动事件并设置阈值,实现节点的添加或删除
  • 使用requestAnimateFrame或节流等技术优化滚动事件的处理,减少不必要的计算和DOM操作