如何使用 Vue 的内置机制预取图像
Posted
技术标签:
【中文标题】如何使用 Vue 的内置机制预取图像【英文标题】:How to prefetch an image using Vue's built-in mechanism 【发布时间】:2019-06-08 20:57:26 【问题描述】:我有一个带有 Vue CLI 的应用程序。当应用程序加载时,当用户单击按钮时,我会看到一堆带有过渡效果的图像。问题是当用户单击一个按钮时,相应的图像才开始加载,这意味着大部分动画都在此之前完成。这使得体验非常不稳定,因为图像在过渡过程中突然出现,取代了其他元素。我想在网站加载时预取它们。
This answer 建议使用Image
类。但是,根据Vue CLI docs,Vue 内部为此使用了自己的插件preload-webpack-plugin,显然是can be configured。
我尝试对其进行配置以使其预加载图像:
vue.config.js
const htmlWebpackPlugin = require('html-webpack-plugin');
const PreloadWebpackPlugin = require('@vue/preload-webpack-plugin');
module.exports =
configureWebpack:
plugins: [
new HtmlWebpackPlugin(),
new PreloadWebpackPlugin(
rel: 'prefetch',
as (entry)
if (/\.css$/.test(entry)) return 'style';
if (/\.woff$/.test(entry)) return 'font';
if (/\.png$/.test(entry)) return 'image';
return 'script';
)
]
这只会破坏最终的index.html
,使其内部没有构建脚本和样式。
如果我删除这一行:
new HtmlWebpackPlugin(),
网站仍在加载,但图像未预取。就像我从未在 vue.config.js
文件中做任何事情一样。
如何正确设置?
编辑: 在 Vue 组件中,我使用 require()
加载图像,这意味着它们通过 Webpack。例如:
<img :src="require('../assets/img/' + img)" draggable="false">
编辑:我能够按照 Roy J 在 cmets 中的建议预取图像:
PreloadImages.vue
在我的主要组件中:
<template>
<div style="display: none;">
<img :src="require('../assets/img/foo.png')">
<img :src="require('../assets/img/bar.png')">
<img :src="require('../assets/img/baz.png')">
</div>
</template>
但是,这不是我实际问题的答案 - 它不通过 <link>
标签使用资源提示。这也需要更多的努力,我认为这是一种不好的做法。
【问题讨论】:
您链接到的 Vue 文档似乎建议改用 this。 是的,如果我想硬编码预取元标记。我有一个应该做到这一点的构建系统,我想给 它 满意。如果我将标签放在我的index.html
中,图像将不会通过 Vue 或 Webpack。另外,它不能用于动态资产,因为它们的文件名是散列的。
你能把图片包含在<img>
标签中不可见的地方吗?
我想我可以,但我认为这是一个糟糕的解决方案?首先,我需要复制<img>
标签,这不是 DRY。其次,路径是动态的,这让事情变得更加复杂。
当然,你可以让 img 标签动态化,就像可见标签一样。
【参考方案1】:
解决方案 1。
当用户单击按钮时,您会将图像呈现为不可见状态。
在图像的load
事件中,您可以顺利执行过渡。
如果图像的加载时间通常超过 2 秒,请考虑向用户提供视觉线索,即按钮点击已被记录并填充 即将发生。
这将是技术上正确的解决方案。
解决方案 2。
在生产环境中广泛使用的另一种选择(与 Vue 本身无关)是在页面中加载图像的缩略图(如小 10 倍 - 大约小 100 倍, 是区域)。这可能并不明显,但它们可以很好地替代大型的,而过渡正在进行中 - 您可能还想在它们上试验 CSS blur
过滤器。
缩略图和大图像必须完全重叠,在同一个过渡父级中,大的在下面。在大版本的load
事件中,将缩略图淡出,产生聚焦效果:一个微妙的吸引眼球。
这种方法的一个相当有趣的好处是,如果您将拇指放在顶部(使用opacity: 0
),每当有人尝试下载图像时,他们右键单击拇指并且难以理解为什么他们以如此低的速度下载它水库
在实际加载图像时,除了在图像上添加焦点效果外,一切都几乎相同(就动画而言)。
不干燥,但高效。看起来很专业,一切似乎都可以立即流畅地加载。总体而言,它比其他“正确”解决方案的转换方式更多。这就是为什么它常用于页面性能很重要的网站。
在处理视觉效果时,成为完美就是看起来完美(在用户体验中,感觉/看起来完美)。 古希腊人弯曲他们的柱子,以便从下方观看时直视。
【讨论】:
【参考方案2】:由于 VueJS 已经包含该插件,我认为您必须使用 chainWebpack 对其进行修改。
根据预加载 webpack 插件documentation,您还应该将 include 选项设置为 'allAssets' 值。
在 Webpack 中使用 file-loader 之类的加载器是很常见的 生成特定类型的资产,例如字体或图像。如果你 希望也预加载这些文件,您可以使用包含值 所有资产
所以配置会是这样的:
// vue.config.js
module.exports =
chainWebpack: config =>
config.plugin('preload').tap(options =>
options[0].as = (entry) =>
if (/\.css$/.test(entry)) return 'style';
if (/\.woff$/.test(entry)) return 'font';
if (/\.png$/.test(entry)) return 'image';
return 'script';
options[0].include = 'allAssets'
// options[0].fileWhitelist: [/\.files/, /\.to/, /\.include/]
// options[0].fileBlacklist: [/\.files/, /\.to/, /\.exclude/]
return options
)
通过全新的 Vue-cli 安装,我生成了以下 HTML
<!DOCTYPE html>
<html lang=en>
<head>
<meta charset=utf-8>
<meta http-equiv=X-UA-Compatible content="IE=edge">
<meta name=viewport content="width=device-width,initial-scale=1">
<link rel=icon href=/favicon.ico> <title>vue-preload-images</title>
<link href=/css/app.0b9b292a.css rel=preload as=style>
<!-- Here is the logo image -->
<link href=/img/logo.82b9c7a5.png rel=preload as=image>
<link href=/js/app.30d3ed79.js rel=preload as=script>
<link href=/js/chunk-vendors.3d4cd4b5.js rel=preload as=script>
<link href=/css/app.0b9b292a.css rel=stylesheet>
</head>
<body><noscript><strong>We're sorry but vue-preload-images doesn't work properly without javascript enabled. Please enable it to continue.</strong></noscript>
<div id=app></div>
<script src=/js/chunk-vendors.3d4cd4b5.js> </script> <script src=/js/app.30d3ed79.js> </script> </body> </html>
我希望它对你有用。
【讨论】:
以上是关于如何使用 Vue 的内置机制预取图像的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Vue-CLI 3 中将预取和预加载资源插入到我的自定义 HTML 文件中?