教程[11] 一个在可视界面内加载前端的实例

开篇废话

这几天在弄 ugoira.huggy.moe 的前端,本质是个很简单的网页,就是给出 pixiv 的动图 mp4 格式 然后下载之类的。
整个网页也很简单,使用了 vite.jsef.js 就开搞了
整个网站在打包后甚至在 40kb 以内 平平淡淡才是真
然后就发现了一个问题,一个网页内的视频(也就是 video tag)如果超过 75 个,那么 Chromium 系列浏览器就会拒绝加载余下资源,并且在 console 丢给你一个错误
console and calculator
web preview
也就是直接不渲染了
前排💩山警告,提供大概思路,代码是一次性的,未经过优化,请勿直接抄

分析

一开始我想 iframe 套娃的,觉得太麻烦就懒得搞了。
然后老宋在群里提了下 <video> 可以动态加载,从池里抽 DOM
主要逻辑就是这样的:
只加载用户可视页面里面资源,不可见区域的资源使用奇怪的办法占位或者隐藏(删掉)
Twitter 的思路是这样的的:
css: min-height:36519px; 是拿来填充高度的
然后下面的 transform: translateY(4703px); 是拿来当 div 的假高度的

最后效果就是:只在前端可视范围内渲染大概 18 个 Tweet(不知道宽屏或者窄屏幕这个数量会不会变化)
并且滚动没有什么问题,是动态补偿的 每个 Tweet 都被安排得明明白白
而且媒体流都是手动点击才有的
这样的操作就能减少很多渲染压力了,浏览器访问也更不卡了
Twitter-web

不过显然我这种简单的站不需要像 Twitter 优化地这么彻底,我们只需要 <video> 按需加载就可以了,文字部分全部留着够了

最后思路:
监听滚动事件,然后动态更新需要渲染的 div 不需要的 div 就直接清空 + 占个高度(不占高度滚动条会很鬼畜)

实践

一开始先写按需渲染的函数,参考
lazyload
sid 就是要加载的项目,然后 count 是前后加载多少个(默认是4) 然后不在 sid +- count 范围内(如果 sid = 2, count = 2 那么 0 1 2 3 4 会被渲染,其它的不会被渲染)
最后使用了九个 <video> 作为占位的,也就是在一个页面里面最多会出现 9 个 <video> 也就不会有一开始的错误了 页面滚动也许会快点
videoPlayers
(原生写法应为 document.createElement('video')
然后再监听一下滚动事件或者 1 秒轮询一次
// 如果是监听滚动事件,那么优化要做好来,我直接监听的话滚动就开始卡了(因为滚动一下就会 update 一下)
最后我使用了轮询 也就是 setInterval
拿了个 scroll_Y 当缓存,判断是否需要执行
scroll listen
这里判断 可视的 div offsetTop > Y 时,就喂给前面的按需加载 (videoloader) 函数,这样就加载到了前后 9 个视频了
最后效果:

总结

这种懒加载之前也听说过,不过现在真正写过类似的还是第一次,还是记录下思路。

最终目的就是 减少 DOM 的渲染,减轻浏览器渲染的负担,按照这个思路想就行了。

占位的的长宽我就不太想搞了,所以滚动条还是有点鬼畜的,这个懒得再优化了。(视频的宽度和高度是有的,但是要按照比例缩放之类的,还要根据各种宽度的设备作适配,懒了)

代码最后写糊了,不过还能用就是了,反正功能也不多 全丢在一个 .js 里面了,然后这个项目我想要的功能也基本加完了,如果哪天想到新功能也可以再加下。

欢迎访问 https://ugoira.huggy.moe