使用require.context实现优雅的预加载

这篇具有很好参考价值的文章主要介绍了使用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即可!文章来源地址https://www.toymoban.com/news/detail-434259.html

到了这里,关于使用require.context实现优雅的预加载的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag

    最近在做一个人脸识别相关的项目,调用context.startActivity(intent)方法,报错如下: android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want? 分析:Activity继承自Context,查看Context.startActivity(Intent, Bundle),下

    2024年02月15日
    浏览(47)
  • 使用SpringBoot优雅的实现文件上传

    文件上传,也称为upload,是指将本地图片、视频、音频等文件上传到服务器上,可以供其他用户浏览或下载的过程。文件上传在项目中应用非常广泛,我们经常发微博、发微信朋友圈都用到了文件上传功能。 服务端要接收客户端页面上传的文件,通常都会使用Apache的两个组件

    2024年02月11日
    浏览(45)
  • 浏览器require加载devextreme-react组件

    十几年前使用了devexpress公司的delphi元件,功能很强。它们的html元件devextreme,功能表现类似,也行强。 devextreme和devextreme-react,我使用的是23.2.3版本。 官方推荐的用法,都是要经过build: 经过约12秒的build,出来的html中有一个bundle.js,大小为12.5M。 它的模式是MPA,用babel把r

    2024年01月23日
    浏览(53)
  • R语言【base】——library(),require():加载/连接并列出包

    Package  base  version 4.2.0 library 和 require 加载并连接附加包。 参数【package,help】:包的名称,以名称或字面值字符串或字符串的形式给出,具体取决于是否使用character.only为FALSE(默认)或TRUE。 参数【pos】:检索的名称空间的位置。也可以是当前检索位置的名称,由search()指定。

    2024年02月22日
    浏览(38)
  • DyLoRA:使用动态无搜索低秩适应的预训练模型的参数有效微调

    又一个针对LoRA的改进方法: DyLoRA: Parameter-Efficient Tuning of Pretrained Models using Dynamic Search-Free Low Rank Adaptation https://arxiv.org/pdf/2210.07558v2.pdf https://github.com/huawei-noah/KD-NLP/tree/main/DyLoRA LoRA存在的问题 : rank的值是固定的,训练完成后不能修改。 优化rank的值需要大量的搜索和努力。

    2023年04月20日
    浏览(48)
  • springboot3使用自定义注解+AOP+redis优雅实现防重复提交

      ⛰️个人主页:     蒾酒 🔥 系列专栏 :《spring boot实战》 🌊 山高路远,行路漫漫,终有归途 目录 写在前面 实现思路 实现步骤 1.定义防重复提交注解 2.编写一个切面去发现该注解然后执行防重复提交逻辑 3.测试 依赖条件 1.接口上标记防重复提交注解 2.接口测试 写在最

    2024年04月11日
    浏览(38)
  • 【Redis实践篇】使用Redisson 优雅实现项目实践过程中的5种场景

    Redisson是一个基于Redis的分布式Java对象和数据结构库,它提供了丰富的功能和易于使用的API,使开发人员能够轻松地在分布式环境中操作和管理数据。 作为一个分布式对象和数据结构库,Redisson提供了许多常见的数据结构和算法的实现,包括通用对象桶、二进制流、地理空间

    2024年02月13日
    浏览(52)
  • 使用C++20协程和io_uring优雅地实现异步IO

    距离2020年已经过去很久了,各大编译器对于C++20各项标准的支持也日趋完善,无栈协程也是其中之一,所以我就尝试着拿协程与 io_uring 实现了一下proactor模式,这篇文章用来记录一下我的设计和想法。除此之外,我们能在网络上找到许多优秀的C++20协程的教程以及许多优秀的

    2024年03月27日
    浏览(51)
  • java如何优雅的实现参数非空校验,快速实现参数非空校验,使用@valid实现参数非空校验

    在java项目接口中,有些必传参数需要进行非空校验,如果参数过多,代码会繁杂且冗余,如何优雅的对参数进行非空校验,下面是实现流程 用实体类接收参数,使用非空注解编辑参数内容 使用 @Valid 注解对参数进行拦截,整体进行非空校验 如果是SpringBoot项目,引入web开发包

    2024年02月08日
    浏览(49)
  • 3步实现使用Conda安装本地指定路径下requirement.txt 文件中的包

    第1步:在github项目中下载或者自行生成所需的requirement.txt文件,将其放在任一路径位置。例如 D:requirement.txtrequirement.txt 第2步:使用anaconda prompt直接进入指定环境,例如我这里进入 tat-qa 这个环境。 第3步:直接安装,注意在requirement.txt前指定好本地路径即可。 因为我本次所需环

    2024年02月12日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包