Gambar dinamis Vue.js tidak berfungsi

90

Aku punya kasus di mana di saya Vue.jsdengan webpackaplikasi web, saya perlu untuk menampilkan gambar dinamis. Saya ingin menunjukkan di imgmana nama file gambar disimpan dalam variabel. Variabel itu adalah computedproperti yang mengembalikan Vuexvariabel toko, yang diisi secara asinkron beforeMount.

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

Namun itu bekerja dengan sempurna ketika saya hanya melakukan:

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

Kasus saya mirip dengan biola ini , tetapi di sini ia berfungsi dengan URL img, tetapi di kasus saya dengan jalur file yang sebenarnya, itu tidak berfungsi.

Apa cara yang benar untuk melakukannya?

Saurabh
sumber
1
memecahkan `<v-img: src =" require ( @/assets/+ items.image) "height =" 200px "> </v-img>` yang satu ini juga memecahkan masalah
Mohamed Raza

Jawaban:

98

Saya mendapatkan ini bekerja dengan mengikuti kode

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

dan dalam HTML:

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

Tetapi tidak yakin mengapa pendekatan saya sebelumnya tidak berhasil.

Saurabh
sumber
7
Menurut nickmessing: "Ekspresi di dalam v-bind dijalankan saat runtime, alias webpack pada waktu kompilasi." github.com/vuejs/vue-loader/issues/896
antoine
@Grigio memiliki peningkatan yang bagus untuk jawaban ini: stackoverflow.com/a/47480286/5948587
samlandfried
1
Masalahnya adalah jalur tersebut tidak ada. Seluruh aplikasi vue dikompilasi oleh webpack menjadi satu skrip (dan gambar juga diganti namanya secara normal, menggunakan hash konten). Dengan menggunakan require.context, Anda memaksa file untuk dilihat oleh webpack dan menyelesaikannya ke gambar yang dihasilkan. Periksa tautan yang berfungsi di browser dan Anda akan melihat apa yang saya maksud. Solusi bagus.
estani
Bagaimana jika saya tidak ingin gambar saya ada di folder aset? Bagaimana jika mereka hanya ada di folder publik situs web karena diunggah oleh pengguna area admin?
thinsoldier
halo, saya telah mencoba ini tetapi gagal, kemudian saya menemukan solusi lain yang menggunakan literal template. Ini bisa berhasil dan saya ingin membagikan ini: stackoverflow.com/questions/57349167/…
lin
82

Berikut ini adalah singkatan yang akan digunakan webpack agar tidak perlu digunakan require.context.

HTML:

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

Metode Vue:

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

Dan saya menemukan bahwa 2 paragraf pertama di sini menjelaskan mengapa ini berhasil? baik.

Harap diperhatikan bahwa meletakkan gambar hewan peliharaan Anda di dalam subdirektori merupakan ide yang bagus, daripada memasukkannya ke dalam semua aset gambar Anda yang lain. Seperti:./assets/pets/

Artur Grigio
sumber
`<v-img: src =" require ( @/assets/+ items.image) "height =" 200px "> </v-img>` yang ini juga memecahkan masalah
Mohamed Raza
Ini adalah satu-satunya solusi yang berhasil setelah banyak mencoba ..
makkus
38

Anda bisa mencoba requirefungsinya. seperti ini:

<img :src="require(`@/xxx/${name}.png`)" alt class="icon" />
feng zhang
sumber
Mengapa @simbol itu diperlukan?
membahayakan
1
@simbol tidak diperlukan, itu sering mewakili srcdir Anda saat menggunakan Resolve | webpack (vue-cli sudah mengkonfigurasi ini.).
feng zhang
20

Ada cara lain untuk melakukannya dengan menambahkan file gambar Anda ke folder publik alih-alih aset dan mengaksesnya sebagai gambar statis.

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

Di sinilah Anda perlu meletakkan gambar statis Anda:

masukkan deskripsi gambar di sini

Rukshan Dangalla
sumber
Ini berfungsi untuk saya kecuali untuk tag alt yang saya
hilangkan
1
menyelamatkan saya dari banyak rasa sakit, saya mendapat kesalahan yang aneh: Tidak dapat menemukan modul './undefined' menggunakan kebutuhan, terima kasih
drakkar
1
Saya pikir ini adalah cara untuk pergi, bukan folder aset.
jukenduit
1
kebutuhan dinamis tidak bekerja untuk saya juga di Vue2 terbaru
goodniceweb
8

Taruhan terbaik Anda adalah dengan hanya menggunakan metode sederhana untuk membuat string yang benar untuk gambar pada indeks yang diberikan:

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

kemudian lakukan hal berikut di dalam Anda v-for:

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

Inilah JSFiddle (jelas gambar tidak muncul, jadi saya meletakkan gambar di srcsebelah gambar):

https://jsfiddle.net/q2rzssxr/

craig_h
sumber
Betulkah? Berikut adalah contoh dengan gambar nyata yang tampaknya berfungsi dengan baik: jsfiddle.net/q2rzssxr/1
craig_h
Tidak yakin mengapa, saya membuatnya bekerja dengan kode yang saya tulis di jawaban lain. Contoh Anda bahkan berfungsi tanpa fungsi ini, lihat di sini: jsfiddle.net/9a6Lg2vd/1
Saurabh
Dalam kasus saya, foto sedang diisi secara asinkron menggunakan toko Vuex, mungkin itu ada hubungannya, saya mencoba mensimulasikannya, tetapi tidak berhasil: jsfiddle.net/9a6Lg2vd/2
Saurabh
Kasus saya lebih seperti ini: jsfiddle.net/9a6Lg2vd/4 , tetapi di hewan peliharaan lokal saya mendapatkan data yang diisi dari panggilan ajax, tetapi gambar tidak dapat dirender.
Saurabh
Ini juga berfungsi: jsfiddle.net/9a6Lg2vd/5 , tidak yakin mengapa tidak berfungsi dengan jalur file.
Saurabh
5

Saya juga mengalami masalah ini dan tampaknya kedua jawaban yang paling banyak dipilih berfungsi tetapi ada masalah kecil, webpack membuat kesalahan ke konsol browser (Kesalahan: Tidak dapat menemukan modul './undefined' di webpackContextResolve) yang tidak terlalu bagus.

Jadi saya telah menyelesaikannya dengan sedikit berbeda. Seluruh masalah dengan variabel di dalam pernyataan memerlukan adalah bahwa pernyataan yang membutuhkan dijalankan selama bundling dan variabel di dalam pernyataan itu hanya muncul selama eksekusi aplikasi di browser. Jadi webpack melihat gambar yang diperlukan sebagai tidak terdefinisi dengan cara apa pun, karena selama kompilasi variabel itu tidak ada.

Apa yang saya lakukan adalah menempatkan gambar acak ke dalam pernyataan yang dibutuhkan dan menyembunyikan gambar itu di css, jadi tidak ada yang melihatnya.

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

Gambar datang sebagai bagian dari informasi dari database melalui Vuex dan dipetakan ke komponen sebagai sebuah komputasi

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

Jadi, setelah informasi ini tersedia, saya menukar gambar awal ke gambar asli

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

Inilah jawaban yang sangat sederhana. : D

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

Anda dapat menggunakan blok coba tangkap untuk membantu dengan gambar yang tidak ditemukan

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
sumber
2
<img src="../assets/graph_selected.svg"/>

Jalur statis diselesaikan oleh Webpack sebagai ketergantungan modul melalui loader. Tapi untuk jalur dinamis Anda perlu menggunakan membutuhkan untuk menyelesaikan jalur. Anda kemudian dapat beralih di antara gambar menggunakan variabel boolean & ekspresi terner.

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

Dan tentu saja mengubah nilai boolean melalui beberapa event handler.

Ron16
sumber
Terima kasih, ini berfungsi :src="require(../assets/category_avatar/baby_kids.jpeg)"
Mohamed Raza
0

Nah, cara terbaik dan termudah yang berhasil bagi saya adalah dengan cara ini saya mengambil data dari API ..

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

metode getPic mengambil satu parameter yaitu nama file dan mengembalikan jalur absolut file mungkin dari server Anda dengan nama file sederhana ...

berikut adalah contoh komponen di mana saya menggunakan ini:

<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>
pengguna8453321
sumber
0

Saya mengalami masalah yang sama. Ini berhasil untuk saya dengan mengubah '../assets/' menjadi './assets/'.

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

Coba impor gambar seperti ini, karena Webpack harus tahu tentang ketergantungannya

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