Les images dynamiques Vue.js ne fonctionnent pas

90

J'ai un cas où dans mon Vue.jsavec l' webpackapplication web, j'ai besoin d'afficher des images dynamiques. Je veux montrer imgoù le nom de fichier des images est stocké dans une variable. Cette variable est une computedpropriété qui renvoie une Vuexvariable de magasin, qui est remplie de manière asynchrone sur beforeMount.

<div class="col-lg-2" v-for="pic in pics">
   <img v-bind:src="'../assets/' + pic + '.png'" v-bind:alt="pic">
</div>

Cependant, cela fonctionne parfaitement quand je fais juste:

<img src="../assets/dog.png" alt="dog">

Mon cas est similaire à ce violon , mais ici cela fonctionne avec une URL img, mais dans le mien avec des chemins de fichiers réels, cela ne fonctionne pas.

Quelle devrait être la bonne façon de le faire?

Saurabh
la source
1
résolu `<v-img: src =" require ( @/assets/+ items.image) "height =" 200px "> </v-img>` celui-ci a également résolu le problème
Mohamed Raza

Réponses:

98

J'ai fait fonctionner cela en suivant le code

  getImgUrl(pet) {
    var images = require.context('../assets/', false, /\.png$/)
    return images('./' + pet + ".png")
  }

et en HTML:

<div class="col-lg-2" v-for="pic in pics">
   <img :src="getImgUrl(pic)" v-bind:alt="pic">
</div>

Mais je ne sais pas pourquoi mon approche précédente n'a pas fonctionné.

Saurabh
la source
7
Selon nickmessing: "L'expression à l'intérieur de v-bind est exécutée au moment de l'exécution, les alias webpack au moment de la compilation." github.com/vuejs/vue-loader/issues/896
antoine
@Grigio a une belle amélioration à cette réponse: stackoverflow.com/a/47480286/5948587
samlandfried
1
Le problème était que le chemin n'existe pas. L'ensemble de l'application vue est compilé par webpack en un seul script (et les images sont également renommées normalement, en utilisant un hachage du contenu). En utilisant require.context, vous forcez les fichiers à être vus par webpack et à résoudre l'image résultante. Vérifiez le lien de travail dans le navigateur et vous verrez ce que je veux dire. Excellente solution.
estani le
Que faire si je ne souhaite pas que mes images soient dans le dossier des ressources? Que faire s'ils n'existent que dans le dossier public du site Web car ils sont téléchargés par les utilisateurs de la zone d'administration?
thinsoldier
bonjour, j'ai essayé cela mais j'ai échoué, puis j'ai trouvé une autre solution qui utilise des modèles littéraux. Cela pourrait fonctionner et je veux partager ceci: stackoverflow.com/questions/57349167/...
lin
82

Voici un raccourci que Webpack utilisera pour que vous n'ayez pas à l'utiliser require.context.

HTML:

<div class="col-lg-2" v-for="pic in pics">
    <img :src="getImgUrl(pic)" v-bind:alt="pic">
</div>

Méthode Vue:

getImgUrl(pic) {
    return require('../assets/'+pic)
}

Et je trouve que les 2 premiers paragraphes ici expliquent pourquoi cela fonctionne? bien.

Veuillez noter que c'est une bonne idée de placer les images de vos animaux de compagnie dans un sous-répertoire, au lieu de les insérer avec tous vos autres éléments d'image. Ainsi:./assets/pets/

Artur Grigio
la source
`<v-img: src =" require ( @/assets/+ items.image) "height =" 200px "> </v-img>` celui-ci a également résolu le problème
Mohamed Raza
C'était la seule solution de travail après beaucoup d'essais ..
makkus
38

Vous pouvez essayer la requirefonction. comme ça:

<img :src="require(`@/xxx/${name}.png`)" alt class="icon" />
feng zhang
la source
Pourquoi ce @symbole est-il nécessaire?
mal
1
@Le symbole n'est pas obligatoire, il représente offten votre répertoire srclorsque vous utilisez Resolve | webpack (vue-cli est déjà configuré ceci.).
feng zhang
20

Il existe une autre façon de le faire en ajoutant vos fichiers image à un dossier public au lieu d'actifs et en accédant à ceux-ci sous forme d'images statiques.

<img :src="'/img/' + pic + '.png'" v-bind:alt="pic" >

C'est là que vous devez mettre vos images statiques:

entrez la description de l'image ici

Rukshan Dangalla
la source
Cela a fonctionné pour moi, sauf pour la balise alt, j'ai omis le v-bind
StefanBob
1
m'a sauvé beaucoup de douleur, j'ai eu une erreur étrange: Impossible de trouver le module './undefined' en utilisant require, merci
drakkar
1
Je pense que c'est la voie à suivre, pas le dossier des actifs.
jukenduit
1
dynamic require ne fonctionnait pas pour moi aussi dans la dernière Vue2
goodniceweb
8

Votre meilleur pari est d'utiliser simplement une méthode simple pour créer la chaîne correcte pour l'image à l'index donné:

methods: {
  getPic(index) {
    return '../assets/' + this.pics[index] + '.png';
  }
}

puis procédez comme suit dans votre v-for:

<div class="col-lg-2" v-for="(pic, index) in pics">
   <img :src="getPic(index)" v-bind:alt="pic">
</div>

Voici le JSFiddle (évidemment les images ne s'affichent pas, j'ai donc mis l'image à srccôté de l'image):

https://jsfiddle.net/q2rzssxr/

craig_h
la source
Vraiment? Voici un exemple d'images réelles qui semble fonctionner correctement
craig_h
Je ne sais pas pourquoi, je l'ai fait fonctionner par le code que j'ai écrit dans une autre réponse. Votre exemple fonctionne même sans cette fonction, voir ici: jsfiddle.net/9a6Lg2vd/1
Saurabh
Dans mon cas, les photos sont remplies de manière asynchrone à l'aide du magasin Vuex, peut-être que cela a quelque chose à faire à ce sujet, j'ai essayé de le simuler, mais je n'ai pas fonctionné: jsfiddle.net/9a6Lg2vd/2
Saurabh
Mon cas ressemble plus à celui-ci: jsfiddle.net/9a6Lg2vd/4 , mais dans mes animaux de compagnie locaux, les données sont remplies à partir d'un appel ajax, mais les images ne sont pas rendues.
Saurabh
Cela fonctionne également: jsfiddle.net/9a6Lg2vd/5 , je ne sais pas pourquoi cela ne fonctionne pas avec les chemins de fichiers.
Saurabh
5

J'ai également rencontré ce problème et il semble que les deux réponses les plus votées fonctionnent mais il y a un petit problème, webpack jette une erreur dans la console du navigateur (Erreur: Impossible de trouver le module './undefined' sur webpackContextResolve), ce qui n'est pas très agréable.

Donc je l'ai résolu un peu différemment. Le problème avec la variable à l'intérieur de l'instruction require est que l'instruction require est exécutée pendant le regroupement et la variable à l'intérieur de cette instruction n'apparaît que pendant l'exécution de l'application dans le navigateur. Ainsi, Webpack considère l'image requise comme non définie dans les deux cas, car lors de la compilation, cette variable n'existe pas.

Ce que j'ai fait, c'est de placer une image aléatoire dans une instruction require et de cacher cette image en css pour que personne ne la voie.

// template
<img class="user-image-svg" :class="[this.hidden? 'hidden' : '']" :src="userAvatar" alt />

//js
data() {
  return {
    userAvatar: require('@/assets/avatar1.svg'),
    hidden: true
  }
}

//css
.hidden {display: none}

L'image fait partie des informations de la base de données via Vuex et est mappée au composant en tant que

computed: {
  user() {
    return this.$store.state.auth.user;
  }
}

Donc, une fois que ces informations sont disponibles, je remplace l'image initiale par l'image réelle

watch: {
  user(userData) {
    this.userAvatar = require(`@/assets/${userData.avatar}`);
    this.hidden = false;
  }
}
Alonad
la source
4

Voici une réponse très simple. :RÉ

<div class="col-lg-2" v-for="pic in pics">
   <img :src="`../assets/${pic}.png`" :alt="pic">
</div>
diamant
la source
3

Vous pouvez utiliser le bloc try catch pour vous aider avec les images non trouvées

getProductImage(id) {
          var images = require.context('@/assets/', false, /\.jpg$/)
          let productImage = ''
          try {
            productImage = images(`./product${id}.jpg`)
          } catch (error) {
            productImage = images(`./no_image.jpg`)
          }
          return productImage
},
Gabriel Fernandez
la source
2
<img src="../assets/graph_selected.svg"/>

Le chemin statique est résolu par Webpack en tant que dépendance de module via le chargeur. Mais pour le chemin dynamique, vous devez utiliser require pour résoudre le chemin. Vous pouvez ensuite basculer entre les images à l'aide d'une variable booléenne et d'une expression ternaire.

<img :src="this.graph ? require( `../assets/graph_selected.svg`) 
: require( `../assets/graph_unselected.svg`) " alt="">

Et bien sûr, basculez la valeur du booléen via un gestionnaire d'événements.

Ron16
la source
Merci, cela fonctionne :src="require(../assets/category_avatar/baby_kids.jpeg)"
Mohamed Raza
0

eh bien, le moyen le plus simple et le plus efficace qui a fonctionné pour moi était celui dont je récupérais des données à partir d'une API.

methods: {
       getPic(index) {
    return this.data_response.user_Image_path + index;
  }
 }

la méthode getPic prend un paramètre qui est le nom du fichier et elle renvoie le chemin absolu du fichier peut-être depuis votre serveur avec le nom de fichier simple ...

voici un exemple de composant où j'ai utilisé ceci:

<template>
    <div class="view-post">
        <div class="container">
     <div class="form-group">
             <label for=""></label>
             <input type="text" class="form-control" name="" id="" aria-describedby="helpId" placeholder="search here">
             <small id="helpId" class="form-text user-search text-muted">search for a user here</small>
           </div>
           <table class="table table-striped ">
               <thead>
                   <tr>
                       <th>name</th>
                       <th>email</th>
                       <th>age</th>
                       <th>photo</th>
                   </tr>
                   </thead>
                   <tbody>
                       <tr v-bind:key="user_data_get.id"  v-for="user_data_get in data_response.data">
                           <td scope="row">{{ user_data_get.username }}</td>
                           <td>{{ user_data_get.email }}</td>
                           <td>{{ user_data_get.userage }}</td>
                           <td><img :src="getPic(user_data_get.image)"  clas="img_resize" style="height:50px;width:50px;"/></td>
                       </tr>

                   </tbody>
           </table>
        </div>

    </div>
</template>

<script>
import axios from 'axios';
export default {
     name: 'view',
  components: {

  },
  props:["url"],
 data() {
     return {
         data_response:"",
         image_path:"",
     }
 },
 methods: {
       getPic(index) {
    return this.data_response.user_Image_path + index;
  }
 },
 created() {
     const res_data = axios({
    method: 'post',
    url: this.url.link+"/view",
   headers:{
     'Authorization': this.url.headers.Authorization,
     'content-type':this.url.headers.type,
   }
    })
    .then((response)=> {
        //handle success
      this.data_response = response.data;
      this.image_path = this.data_response.user_Image_path;
       console.log(this.data_response.data)
    })
    .catch(function (response) {
        //handle error
        console.log(response);
    });
 },
}
</script>


<style scoped>

</style>
user8453321
la source
0

J'ai rencontré le même problème. Cela a fonctionné pour moi en remplaçant «../assets/» par «./assets/».

 <img v-bind:src="'./assets/' + pic + '.png'" v-bind:alt="pic">
Bex
la source
-1

Essayez d'importer une image comme celle-ci, car Webpack devrait connaître sa dépendance

    <ul>
              <li v-for="social in socials" 
              v-bind:key="social.socialId"
              >

                <a :href="social.socialWeb" target="_blank">
                  <img class="img-fill" :id="social.socialId" :src="social.socialLink" :alt="social.socialName">
                </a>
              </li>

            </ul>

<script>
        import Image1 from '@/assets/images/social/twitter.svg'
        import Image2 from '@/assets/images/social/facebook.svg'
        import Image3 from '@/assets/images/social/rss.svg'
        export default {
          data(){
            return{
              socials:[{         
                   socialId:1,         
                   socialName: "twitter",
                   socialLink: Image1,
                   socialWeb: "http://twitter.com"
              },
      {
          socialId:2,
          socialName: "facebook",
           socialLink: Image2,
           socialWeb: "http://facebook.com"

      },
      {
          socialId:3,
          socialName: "rss",
           socialLink: Image3,
           socialWeb: "http://rss.com"
      }]

 </script>
perun10
la source