如何使用Vue.js预加载图片?

22

我有一个使用Vue.Js(使用webpack)的小应用程序。我有一个过渡部分,当用户单击按钮时,内容会发生变化。它是一个简单的DIV元素,其中包含一个IMG子元素。我的问题是,当用户单击按钮时,下一个图像将实时加载,并且速度很慢,因此我需要预加载这些图像。

我尝试了不同的方法,但无法使图像被预加载。问题在于:

  • 只有第一张图片是DOM的一部分,在页面显示时,因此其他图片不会被加载。好吧,这是正常行为。

  • 我无法通过使用图像数组的简单for循环(JavaScript预加载图像)来预加载图像,因为图像将由唯一的查询字符串请求(1),因此预加载的图像名称将与请求的图像名称不匹配。

  • 我尝试使用require()加载图像,并将其绑定到IMG标记的src属性。它也没有解决我的问题,当新的DIV插入到DOM中时,图像仍然会在单击后实时加载。

我的简化单文件组件(.vue)看起来像这样:

<template>
    <!-- [FIRST] -->
    <div v-if="contentId == 0">
      <transition
        enter-active-class="animated fadeIn"
        leave-active-class="animated fadeOut"
        mode="out-in">
        <img :src="images.firstScreenShot" key="firstImage">
      </transition>
    </div>
    <!-- [/FIRST] -->

    <!-- [SECOND] -->
    <div v-else-if="contentId == 1">
      <transition
        enter-active-class="animated fadeIn"
        leave-active-class="animated fadeOut"
        mode="out-in">

        <img :src="images.secondScreenShot" key="secondImage">
      </transition>
    </div>
    <!-- [/SECOND] -->
</template>
<script>
    export default {
        data() {
            return {
                contentId: 0,
                images: {
                    firstScreenShot: require('./assets/first-screen-shot.png'),
                    secondScreenShot: require('./assets/second-screen-shot.png'),
                }
            }
        }
    }
</script>

我刚开始学习Vue.js,也许我的做法不太好。请告诉我什么是好的做法!

3个回答

21

我在浏览器中快速尝试过,但似乎只在控制台中工作。你似乎可以使用Javascript Image对象来预加载图片:

https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/Image

你可以像这样创建一个新的Image对象:

const image = new Image();

然后您可以为该图像分配一个 src 值:

image.src = 'test.jpg'
当您立即使用数据提供src属性时,浏览器将触发网络请求,这应足以使图像加载并缓存。这样,您就不必将这些图像插入到DOM中。
如果我理解有误,请有人纠正我。尚未完全尝试出来。

首先,感谢您的回答!我也尝试过这个方法,但有趣的是它对我也没有起作用。我会再试一次这种方法,并写下结果...也许我犯了一个错误... - user6338195
通过 Chrome 网络选项卡检查网络请求是否实际触发图像。您还可以通过控制台手动尝试进行测试。 - Stephan-v
@EdmundElmer 我遇到了同样的问题。你找到解决方法了吗? - Mekeor Melire
2
你也可以使用document.createElement('img').setAttribute('src', '/static/myimage');,但本质上是一样的,两者都可以工作。 - Daniel
可以正常工作。请注意,每个新的图像实例将预加载一张图片,因此必须为您想要预加载的每个图片创建一个new Image() - samlandfried

5
如果您正在使用模板通过标签来加载图像,您可以使用简单的HTML代码通过rel="preload"预加载图像。
例如:
<img :src="images.secondScreenShot" key="secondImage" rel="preload">

这不起作用,因为就DOM而言,在您显示它并放置src之前,该标记不存在。至少对我来说,在for循环中它不起作用。您有其他情境可以让它工作吗? - Mig
我认为@Fraccier的意思是在页面加载时通过循环创建img元素,为稍后需要的每个图像URL隐藏这些元素,并通过CSS无限期地隐藏这些元素。因此,URL已经预加载到浏览器缓存中,并且可以被其他元素自动访问。基本上是让浏览器来完成繁重的工作。这个人采用了类似的方法,对我来说效果很好 - onewaveadrian

4

我创建了一个函数,只需通过参数发送要加载的图像对象。

在路由器中

import Digital from '../../images/digital';
import { loadImage } from '../LoadImage';
...

const router = new Router({
  routes: [
    {
      path: '/',
      name: 'welcome',
      component: Welcome,
      beforeEnter(to, from, next) {
         loadImage(Digital);
      }
   }
]

我的函数

export function loadImage(imagesObject) {
  Object.keys(imagesObject).map((key, index) => {
    const img = new Image();
    img.src = imagesObject[key];
  });
}

希望它有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接