web-dev-qa-db-fra.com

Comment extraire une image à l'aide du mécanisme intégré de Vue

J'ai une application avec la CLI Vue. Lorsque l'application se charge, j'ai un tas d'images qui apparaissent avec une transition lorsqu'un utilisateur clique sur un bouton. Le problème est que lorsque l'utilisateur clique sur un , l'image correspondante commence alors à se charger, ce qui signifie que la plupart de l'animation est effectuée jusque-là. Cela rend l'expérience assez saccadée car les images apparaissent soudainement pendant la transition, déplaçant d'autres éléments. Je veux les précharger lorsque le site charges.

Cette réponse suggère d'utiliser la classe Image. Cependant, selon les Vue CLI docs , Vue utilise en interne son propre plugin pour cela, preload-webpack-plugin , et il semble peut être configuré .

J'ai essayé de le configurer pour qu'il précharge les images:

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';
        }
      })
    ]
  }
}

Cela ne parvient qu'à foutre le index.html Final, le laissant sans les scripts de construction et les styles à l'intérieur.

Si je supprime cette ligne:

      new HtmlWebpackPlugin(),

Le site se charge toujours mais les images ne sont pas prérécupérées. C'est la même chose que si je n'ai jamais rien fait dans le fichier vue.config.js.

Comment le configurer correctement?


Edit: Dans les composants Vue, j'utilise require() pour charger les images, ce qui signifie qu'elles passent via Webpack. Par exemple:

<img :src="require('../assets/img/' + img)" draggable="false">

Edit: J'ai pu récupérer les images comme Roy J l'a suggéré dans les commentaires:

PreloadImages.vue Dans mon composant principal:

<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>

Cependant, ce n'est pas la réponse à ma question réelle - il n'utilise pas d'indications de ressources via les balises <link>. Cela demande également plus d'efforts et je pense que c'est une mauvaise pratique.

14
dodov

Comme le plugin est déjà inclus par VueJS, je pense que vous devez le modifier avec chainWebpack .

Selon le plugin de préchargement de webpack documentation , vous devez également définir l'option include sur ' la valeur de allAssets.

Il est très courant dans Webpack d'utiliser des chargeurs tels que le chargeur de fichiers pour générer des ressources pour des types spécifiques, tels que des polices ou des images. Si vous souhaitez également précharger ces fichiers, vous pouvez utiliser include avec une valeur allAssets

La configuration sera donc quelque chose comme ceci:

// 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
        })
    }
}

Avec une nouvelle installation de Vue-cli, j'ai obtenu le code HTML suivant généré

<!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>

J'espère que cela fonctionnera pour vous.

2
lbineau

Solution 1.

Lorsque l'utilisateur clique sur le bouton, vous rendez votre image dans un état non visible.

Sur l'événement load de l'image, vous effectuez votre transition en douceur.

Si le chargement de l'image prend généralement plus de 2 secondes, pensez à donner à l'utilisateur un indice visuel du clic du bouton était enregistré et des trucs est sur le point de se produire.

Ce serait la solution techniquement correcte .


Solution 2.

Une alternative, largement utilisée dans les environnements de production (et n'ayant rien à voir avec Vue per-se), consiste à charger les vignettes des images de votre page (comme 10 fois plus petites - ce qui est ~ 100 fois plus petite, étant des zones). Ce n'est peut-être pas évident, mais ils remplacent très bien les grands, tandis que la transition est en cours - vous pouvez également essayer le filtre CSS blur sur eux .

La vignette et la grande image doivent être parfaitement superposées, dans le même parent de transition, avec la grande en dessous. Sur load événement de la grande version, atténuez la vignette, provoquant un effet de focus-in: un subtil accroche-regard.
Un avantage assez drôle de cette méthode est que, si vous laissez les pouces sur le dessus (avec opacity: 0), chaque fois que quelqu'un essaie de télécharger une image, il fait un clic droit sur le pouce et a du mal à comprendre pourquoi il la télécharge à une résolution aussi basse.

Tout est à peu près le même (en termes d'animations) avec l'ajout d'un effet de mise au point sur l'image, lorsqu'elle est effectivement chargée.

Pas SEC, mais efficace. Semble professionnel, tout semble se charger instantanément et en douceur. Dans l'ensemble, il convertit bien plus que d'autres solutions "correctes". C'est pourquoi il est couramment utilisé sur les sites Web où les performances des pages sont importantes.


En ce qui concerne les visuels, être parfait est regarder parfait (et, dans UX, sensation/apparence parfait).
Les anciens Grecs pliaient leurs colonnes pour qu'ils aient l'air droits quand on les regardait d'en bas.

0
tao