Die dynamischen Bilder von Vue.j funktionieren nicht


90

Ich habe einen Fall , in dem in meinem Vue.jsmit webpackWeb - App, ich brauche dynamische Bilder anzuzeigen. Ich möchte zeigen, imgwo der Dateiname von Bildern in einer Variablen gespeichert ist. Diese Variable ist eine computedEigenschaft, die eine VuexGeschäftsvariable zurückgibt, die asynchron aufgefüllt wird beforeMount.

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

Es funktioniert jedoch perfekt, wenn ich es gerade tue:

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

Mein Fall ähnelt dieser Geige , aber hier funktioniert es mit der IMG-URL, aber in meinem Fall mit tatsächlichen Dateipfaden funktioniert es nicht.

Was sollte der richtige Weg sein, um es zu tun?


1
gelöst `<v-img: src =" require ( @/assets/+ items.image) "height =" 200px "> </ v-img>` dieses Problem wurde ebenfalls gelöst
Mohamed Raza

Antworten:


98

Ich habe dies durch folgenden Code zum Laufen gebracht

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

und in HTML:

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

Aber nicht sicher, warum mein früherer Ansatz nicht funktioniert hat.


7
Laut nickmessing: "Der Ausdruck in v-bind wird zur Laufzeit ausgeführt, Webpack-Aliase zur Kompilierungszeit." github.com/vuejs/vue-loader/issues/896
Antoine

@Grigio hat eine nette Verbesserung zu dieser Antwort: stackoverflow.com/a/47480286/5948587
samlandfried

1
Das Problem war, dass der Pfad nicht existiert. Die gesamte Vue-App wird per Webpack in einem einzigen Skript kompiliert (und Bilder werden auch normal umbenannt, indem ein Hash des Inhalts verwendet wird). Mit require.context erzwingen Sie, dass die Dateien vom Webpack angezeigt werden, und lösen sie in das resultierende Bild auf. Überprüfen Sie den funktionierenden Link im Browser und Sie werden sehen, was ich meine. Tolle Lösung.
Estani

Was ist, wenn ich nicht möchte, dass sich meine Bilder im Assets-Ordner befinden? Was ist, wenn sie nur im öffentlichen Ordner der Website vorhanden sind, weil sie von Benutzern des Administrationsbereichs hochgeladen wurden?
Thinsoldier

Hallo, ich habe es versucht, bin aber gescheitert. Dann habe ich eine andere Lösung gefunden, die Vorlagenliterale verwendet. Es könnte funktionieren und ich möchte dies teilen: stackoverflow.com/questions/57349167/…
lin

82

Hier ist eine Abkürzung, die Webpack verwendet, damit Sie sie nicht verwenden müssen require.context.

HTML:

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

Vue-Methode:

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

Und ich finde, dass die ersten beiden Absätze hier erklären, warum dies funktioniert? Gut.

Bitte beachten Sie, dass es eine gute Idee ist, Ihre Haustierbilder in ein Unterverzeichnis zu stellen, anstatt sie mit all Ihren anderen Bildelementen zu verknüpfen. Wie so:./assets/pets/


`<v-img: src =" require ( @/assets/+ items.image) "height =" 200px "> </ v-img>` Dieser hat auch das Problem gelöst
Mohamed Raza

Dies war die einzige funktionierende Lösung nach vielen Versuchen.
Makkus


20

Es gibt eine andere Möglichkeit, indem Sie Ihre Bilddateien anstelle von Assets zum öffentlichen Ordner hinzufügen und als statische Bilder darauf zugreifen.

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

Hier müssen Sie Ihre statischen Bilder platzieren:

Geben Sie hier die Bildbeschreibung ein


Dies funktionierte für mich mit Ausnahme des Alt-Tags, bei dem ich die V-Bindung weggelassen habe
StefanBob

1
hat mir viel Schmerz erspart, ich habe einen seltsamen Fehler: Ich kann das Modul './undefined' mit require nicht finden, danke
drakkar

1
Ich denke, dies ist der richtige Weg, nicht der Assets-Ordner.
Jukenduit

1
Das dynamische Erfordernis hat auch in der neuesten Version von
Vue2

8

Am besten verwenden Sie einfach eine einfache Methode, um die richtige Zeichenfolge für das Bild am angegebenen Index zu erstellen:

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

dann mache folgendes in deinem v-for:

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

Hier ist die JSFiddle (offensichtlich werden die Bilder nicht angezeigt, daher habe ich das Bild srcneben das Bild gestellt):

https://jsfiddle.net/q2rzssxr/


"Ja wirklich?" Hier ist ein Beispiel mit realen Bildern, das gut zu funktionieren scheint: jsfiddle.net/q2rzssxr/1
craig_h

Ich weiß nicht warum, ich habe es mit dem Code zum Laufen gebracht, den ich in einer anderen Antwort geschrieben habe. Ihr Beispiel funktioniert sogar ohne diese Funktion, siehe hier: jsfiddle.net/9a6Lg2vd/1
Saurabh

In meinem Fall werden Bilder asynchron mit dem Vuex-Speicher gefüllt. Vielleicht hat das etwas zu tun. Ich habe versucht, es zu simulieren, aber es hat nicht funktioniert: jsfiddle.net/9a6Lg2vd/2
Saurabh

Mein Fall ähnelt eher dem folgenden: jsfiddle.net/9a6Lg2vd/4 , aber in meinen lokalen Haustieren werden Daten von einem Ajax-Aufruf ausgefüllt , aber Bilder werden nicht gerendert.
Saurabh

Dies funktioniert auch: jsfiddle.net/9a6Lg2vd/5 , nicht sicher, warum es nicht mit Dateipfaden funktioniert.
Saurabh

5

Ich bin auch auf dieses Problem gestoßen und es scheint, dass beide am besten bewerteten Antworten funktionieren, aber es gibt ein kleines Problem: Webpack wirft einen Fehler in die Browserkonsole (Fehler: Modul './undefined' kann bei webpackContextResolve nicht gefunden werden), was nicht sehr nett ist.

Also habe ich es etwas anders gelöst. Das gesamte Problem mit der Variablen in der require-Anweisung besteht darin, dass die require-Anweisung während der Bündelung ausgeführt wird und die Variable in dieser Anweisung nur während der App-Ausführung im Browser angezeigt wird. Daher sieht Webpack das erforderliche Bild in beiden Fällen als undefiniert an, da diese Variable während der Kompilierung nicht vorhanden ist.

Was ich getan habe, ist, ein zufälliges Bild in die Anforderung zu setzen und dieses Bild in CSS zu verstecken, damit niemand es sieht.

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

Das Bild kommt als Teil der Informationen aus der Datenbank über Vuex und wird der Komponente als berechnet zugeordnet

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

Sobald diese Informationen verfügbar sind, tausche ich das ursprüngliche Bild gegen das echte aus

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

4

Hier ist eine sehr einfache Antwort. : D.

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

3

Sie können try catch block verwenden, um bei nicht gefundenen Bildern zu helfen

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

2
<img src="../assets/graph_selected.svg"/>

Der statische Pfad wird von Webpack als Modulabhängigkeit über den Loader aufgelöst. Für dynamische Pfade müssen Sie jedoch require verwenden, um den Pfad aufzulösen. Sie können dann mit einer booleschen Variablen und einem ternären Ausdruck zwischen Bildern wechseln.

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

Und natürlich können Sie den Wert des Booleschen Werts über einen Ereignishandler umschalten.


Vielen Dank, dass dies funktioniert :src="require(../assets/category_avatar/baby_kids.jpeg)"
Mohamed Raza

0

Nun, der beste und einfachste Weg, der für mich funktioniert hat, war der, bei dem ich Daten von einer API abgerufen habe.

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

Die getPic-Methode verwendet einen Parameter, den Namen der Datei, und gibt den absoluten Pfad der Datei zurück, möglicherweise von Ihrem Server, wobei der Dateiname einfach ist ...

Hier ist ein Beispiel für eine Komponente, in der ich dies verwendet habe:

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

0

Ich bin auf das gleiche Problem gestoßen. Dies funktionierte für mich, indem ich '../assets/' in './assets/' änderte.

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

-1

Versuchen Sie, ein Bild wie dieses zu importieren, da Webpack über seine Abhängigkeit Bescheid wissen sollte

    <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>
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.