使用require.context实现优雅的预加载
前言
在前端开发中,对页面花里胡哨度[注1]要求越高的页面,用到的图片、音频什么的就越多,比如什么结婚请柬、展会请柬、发布会宣传页、数据大屏。虽然现在浏览器不允许网页在没有用户交互的情况下播放音频,但是,我们依旧要在页面展现的同时,准备好所有的静态资源。
注1:花里胡哨度(garish degree),又名难做指数,江湖人称领导开心点
丑陋的预加载
预加载即提前加载,浏览器在请求一张图片时,会缓存到本地,在下次请求同样的地址时,会直接在本地缓存读取(304),在本地读取的时间基本可以忽略不计。如果我们能够在图片未加载完成时给用户一个加载进度,提示用户:“急什么,马上完事!”,则能够有效的提升用户体验。
单张预加载
相信同学都了解图片的预加载:
let img = new Image()
img.src = "@/../../xx.png"
img.onload = () => {
//...
}
这是为大家所熟知的预加载方式,但是这种方法只适用于单张图片的预加载。
那多张怎么做呢?
多张预加载
很简单,我们给图片们定义一个数组就好了
let imagesPathArr = ["@/../../xx.png","@/../../yy.png","..."];
然后我们再用循环去加载这些图片
let count = 0
for (let item of imagesPathArr) {
let img = new Image()
img.src = item
img.onload = () => {
count++
if (count === imagesPathArr.length) {
// ... 加载完成
}
}
}
我们甚至可以通过count/imagesPathArr.length算出加载的百分比 。
没错,但是这种方法加载十张图片还可以,那加载一百张呢?
同学说:“我可以把图片从0-99命名,加载时只需要循环一百次就可以了!”
可以,那么假如我们用python写了一个重命名脚本,把这一百张图片从0-99命名完成。
那么我们的代码就长这样:
for(let i = 0;i<=99;i++){
let img = new Image()
img.src = `@/../../${i}.png`
img.onload = () => {
count++
if (count === imagesPathArr.length) {
// ... 加载完成
}
}
}
ok,看起来没有任何问题,实际上也没有任何问题。
但是在使用过程中,我们会发现,图片的格式不一定是统一的(当然你可以将他们转换成统一的),而且这种方式看起来太丑了,一点也不够优雅。
那么有没有一种方式,优雅的预加载呢?有。
优雅的预加载
要实现优雅的预加载,我们要优哪些方面?
- 第一,我们无需知道加载的图片有多少;
- 第二,我们无需知道加载的图片叫什么;
- 第三,我们无需知道图片的格式是什么。
他的,这听起来就优雅,相当于什么都不用干,就把预加载做出来了!
但是,众所周知,浏览器环境没有直接操作文件系统的能力,我们无法像node一样,直接使用fs,怎么才能做到如上所说的呢?从第一步来看,我们至少要遍历一个父级文件夹吧?
本期的主角登场
require.context
它是一个webpack的api,可以通过这个方法获取一个特定的上下文,用来实现文件的批量自动化导入,如果你使用vite,那么可以使用 import.meta.globEager(),本文只用require.context举例。
好像这个api已经存在了好久了,但是我是最近才知道的,在这里分享给还没用过的同学。
使用语法如下:
let requireModule = require.context(
"../../../public/static/img", // 需要遍历的路径
false, // 是否递归,设置为true会递归到最后一级文件夹
/\.png|\.webp|\.jpg|\.jpeg|\.bmp|\.gif$/ //匹配的正则表达式
);
上述代码匹配了常用的图片格式。
如果我们循环它的key(),会得到类似./xxx.png的项,所以,只要去掉./就得到了文件夹下所有的图片。
所以,我们可以做一个数组来储存所有的图片路径:
let imagesPathArr = [];
for (var i = 0; i < requireModule.keys().length; i++) {
imagesPathArr.push("/static/img/" + requireModule.keys()[i].substr(2, requireModule.keys()[i].length));
}
这样,imagesPathArr就拥有了我们指定文件夹下所有的图片路径了,我们根本无需关心图片有多少、叫什么、什么格式。
下面直接对imagesPathArr进行循环(跟上面一样),导入所有图片:
let count = 0
for (let item of imagesPathArr) {
let img = new Image()
img.src = item
img.onload = () => {
count++
if (count === imagesPathArr.length) {
// 加载完成
}
}
}
最后,我们把所有的逻辑封装成一个函数,并给他套上promise
async loadImgs() {
await new Promise((resolve, reject) => {
this.$store.dispatch('loadingStart', {
text: "正在加载资源"
})
let requireModule = require.context(
"../../../public/static/img",
false,
/\.png|\.webp|\.jpg|\.jpeg|\.bmp|\.gif$/
);
let imagesPathArr = [];
for (var i = 0; i < requireModule.keys().length; i++) {
imagesPathArr.push("/static/img/" + requireModule.keys()[i].substr(2, requireModule.keys()[i].length));
}
let count = 0
for (let item of imagesPathArr) {
let img = new Image()
img.src = item
img.onload = () => {
count++
if (count === imagesPathArr.length) {
this.$store.dispatch('loadingDone')
resolve()
}
}
}
})
},
我们只需在合适的时机,调用该函数,即可全自动的预加载图片了,而且日后往文件夹内新增或者删除图片,都不用管这一段逻辑,它依然可以稳健运行!如果你有加载音频的需求,也是同理,在正则部分加一个.mp3什么的,使用audio.onload即可!
使用require.context实现优雅的预加载的更多相关文章
- iOS教程:如何使用Core Data – 预加载和引入数据
这是接着上一次<iOS教程:Core Data数据持久性存储基础教程>的后续教程,程序也会使用上一次制作完成的. 再上一个教程中,我们只做了一个数据模型,之后我们使用这个数据模型中的数据创 ...
- Javascript图片预加载详解
预加载图片是提高用户体验的一个很好方法.图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度.这对图片画廊及图片占据很大比例的网站来说十分有利,它保证了图片快速.无缝地发布 ...
- ASP.NET MVC3 Razor 调试与预加载
目录(?)[-] 获取服务器信息 FormsAuthenticationSlidingExpiration 属性 MVC3预加载 在ASP.NET MVC3开发中,调试中怎么也是不可缺少的,那对于 ...
- entity framework 数据加载三种方式的异同(延迟加载,预加载,显示加载)
三种加载方式的区别 显示加载: 显示加载
- Entity Framework关联查询以及数据加载(延迟加载,预加载)
数据加载分为延迟加载和预加载 EF的关联实体加载有三种方式:Lazy Loading,Eager Loading,Explicit Loading,其中Lazy Loading和Explicit Lo ...
- Angular.JS + Require.JS + angular-async-loader 来实现异步加载 angular 模块
传统的 angular 应用不支持异步加载模块,必须在 module 启动的时候,所有模块必须预加载进来. 通过使用 angular-async-loader 库,我们可以使用 requirejs 等 ...
- ViewPager的刷新、限制预加载、缓存所有
[框架]: 公共部分:左侧菜单.TitleBar.RadioGroup(3个RadioButton:X.Y.Z) 选择X页面:指示器+ViewPager [要达成的效果]: (1)左侧选择A,进入X页 ...
- 关于禁止ViewPager预加载问题【转】
转自:http://blog.csdn.net/qq_21898059/article/details/51453938#comments 我最近上班又遇到一个小难题了,就是如题所述:ViewPage ...
- ViewPager防止Fragment销毁以及取消Fragment的预加载
存在的问题 1. 默认情况下,ViewPager会根据setOffscreenPageLimit()方法设置的大小,自动预加载2. 还是根据setOffscreenPageLimit()方法设置的大小 ...
- 基于spring的web项目启动时预加载数据到ServletContext
1.要在web启动时预加载数据到ServletContext,实现方法有很多,一种比较简单的方案就是: 1)新建一个bean,定义其初始化方法: <bean id="beanId&qu ...
随机推荐
- 快速排序(Java分治法)
快速排序(Java分治法) 文章目录 快速排序(Java分治法) 0. 分治策略 1.思路步骤 2.代码 3.复杂度分析 3.1 最好情况 3.2 最坏情况 3.3 平均情况 3.4 性能影响因素 4 ...
- 让VMWARE ESXI 虚拟机开机进入BIOS设置
VMware vSphere Client 里面选中需要从光驱启动的客户机,单击右键选择 "编辑设置", 在虚拟机属性的窗口里面选择 "选项 "选项卡 ,单击& ...
- nginx配置权重,ip_hash....
nginx为后端web服务器(apache,nginx,tomcat,weblogic)等做反向代理 几台后端web服务器需要考虑文件共享,数据库共享,session共享问题.文件共享可以使用nfs, ...
- 搬运 nginx代理https
oauth2-client在Nginx代理后遇到的问题和解决方案 2020-01-17 2020-05-27 TECH 30 MINUTES READ (ABOUT 4442 WORDS) OAu ...
- Go_day06
Go基础语法 错误和异常 什么是错误error 错误是指可鞥出现问题的地方出现了问题,这种情况在预料之中 func main() { //打开一个文件 file, err := os.Open(&qu ...
- sql 查询大数据 常用 50列优化
大数据量的问题是很多面试笔试中经常出现的问题,比如baidu google 腾讯 这样的一些涉及到海量数据的公司经常会问到. 下面的方法是我对海量数据的处理方法进行了一个一般性的总结,当然这些方法可能 ...
- Kakao Brain 的开源 ViT、ALIGN 和 COYO 文字-图片数据集
最近 Kakao Brain 在 Hugging Face 发布了一个全新的开源图像文本数据集 COYO,包含 7 亿对图像和文本,并训练了两个新的视觉语言模型 ViT 和 ALIGN ViT 和 A ...
- Ocelot的限流、熔断和负载均衡
一.限流 想要在Ocelot中设置限流,需要在设置如下绿色所示: { "GlobalConfiguration": { "RateLimitOptions": ...
- Kafka 管理【主题、分区、消费者组】
更多内容,前往 IT-BLOG 主题操作 使用 kafka-topics.sh 工具可以执行主题的大部分操作.可以用它创建.修改.删除和查看集群里的主题.要使用该工具的全部功能,需要通过 --zook ...
- 使用 baget 搭建 nuget 私有服务
现在几乎所有语言都提供包管理工具,比如 JavaScript 的 npm ,Java 的 Maven ,Dart 的 pub ..Net 程序当然是 NuGet .NuGet 也出现很多年了,奇怪的是 ...