Vue.js dinamik görüntüleri çalışmıyor


100

Benim bir durum var Vue.jsolan webpackweb uygulaması, Dinamik resimleri görüntülemek gerekir. imgGörüntülerin dosya adlarının bir değişkende nerede saklandığını göstermek istiyorum . Bu değişken, üzerinde zaman uyumsuz olarak doldurulan computedbir Vuexmağaza değişkenini döndüren bir özelliktir beforeMount.

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

Ancak şunu yaptığımda mükemmel çalışıyor:

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

Benim durumum bu kemanla benzer , ancak burada img URL ile çalışıyor, ancak benim gerçek dosya yollarıyla çalışmıyor.

Bunu yapmanın doğru yolu ne olmalı?


1
çözüldü "<v-img: src =" @/assets/required ( + items.image) "height =" 200px "> </v-img>" bu da sorunu çözdü
Mohamed Raza

Yanıtlar:


104

Bunu kodu takip ederek çalıştırdım

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

ve HTML'de:

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

Ama önceki yaklaşımımın neden işe yaramadığından emin değilim.


7
Nickmessing'e göre: "v-bind içindeki ifade çalışma zamanında çalıştırılır, web paketi takma adları derleme zamanında çalıştırılır." github.com/vuejs/vue-loader/issues/896
antoine

@Grigio'nun bu cevaba güzel bir iyileştirmesi var: stackoverflow.com/a/47480286/5948587
samlandfried

1
Sorun, yolun olmamasıydı. Tüm vue uygulaması, web paketi tarafından tek bir komut dosyası halinde derlenir (ve görüntüler de içeriğin bir karması kullanılarak normal olarak yeniden adlandırılır). Require.context'i kullanarak, dosyaları web paketi tarafından görülmeye zorlar ve ortaya çıkan görüntüyü çözersiniz. Tarayıcıdaki çalışma bağlantısını kontrol edin ve ne demek istediğimi göreceksiniz. Harika çözüm.
estani

Ya resimlerimin varlıklar klasöründe olmasını istemiyorsam? Ya yönetici alanı kullanıcıları tarafından yüklendikleri için web sitesinin ortak klasöründe mevcutlarsa ne olur?
thinsoldier

merhaba, bunu denedim ama başarısız oldum, sonra şablon değişmezlerini kullanan başka bir çözüm buldum. İşe yarayabilir ve bunu paylaşmak istiyorum: stackoverflow.com/questions/57349167/…
lin

87

İşte kullanmak zorunda kalmamanız için web paketinin kullanacağı bir kısaltma require.context.

HTML:

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

Vue Yöntemi:

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

Ve ben ilk 2 paragraflar bulmak burada açıklamak niçin bu işler? iyi.

Lütfen evcil hayvanınızın resimlerini diğer tüm resim varlıklarınızla birlikte kullanmak yerine bir alt dizine koymanın iyi bir fikir olduğunu unutmayın. Şöyle:./assets/pets/


"<v-img: src =" require ( @/assets/+ items.image) "height =" 200px "> </v-img>" bu da sorunu çözdü
Mohamed Raza

Bu, çok denedikten sonra çalışan tek
çözümdü

45

requireFonksiyonu deneyebilirsiniz . bunun gibi:

<img :src="require(`@/xxx/${name}.png`)" alt class="icon" />

Bu @sembol neden gerekli?
zarar

1
@sembol gerekli değildir, bu temsil offten srckullanırken dir Çöz | webpack (vue-cli bunu zaten yapılandırmıştır.).
feng zhang

21

Görüntü dosyalarınızı varlıklar yerine ortak klasöre ekleyerek ve bunlara statik görüntüler olarak erişerek yapmanın başka bir yolu var.

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

Statik resimlerinizi koymanız gereken yer burasıdır:

görüntü açıklamasını buraya girin


Bu, v-
bind'i

1
beni çok fazla acıdan kurtardı, garipleştim Hata: './undefined' modülü bulunamıyor, teşekkürler
drakkar

1
Bence bu gidilecek yol, varlıklar klasörü değil.
jukenduit

1
dinamik gereksinim en son Vue2'de benim için de işe yaramadı
goodniceweb

8

En iyi bahsiniz, verilen dizindeki görüntü için doğru dizeyi oluşturmak için basit bir yöntem kullanmaktır:

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

sonra aşağıdakileri kendi içinde yapın v-for:

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

İşte JSFiddle (belli ki resimler gösterilmiyor, bu yüzden resmi resmin srcyanına koydum ):

https://jsfiddle.net/q2rzssxr/


Gerçekten mi? İşte düzgün
craig_h

Neden olduğundan emin değilim, başka bir cevapta yazdığım kodla çalıştırdım. Örneğiniz
Saurabh

Benim durumumda, resimler Vuex mağazası kullanılarak eşzamansız olarak dolduruluyor, belki de bu konuda yapacak bir şeyi var, onu simüle etmeye çalıştım, ancak işe yaramadı: jsfiddle.net/9a6Lg2vd/2
Saurabh

Benim durumum daha çok şuna benziyor: jsfiddle.net/9a6Lg2vd/4 , ancak yerel evcil hayvanımda bir ajax çağrısından veri dolduruluyor, ancak görüntüler işlenmiyor .
Saurabh

Bu da işe yarar : jsfiddle.net/9a6Lg2vd/5 , neden dosya yollarıyla çalışmadığından emin değilim.
Saurabh

6

Ben de bu soruna çarptım ve görünüşe göre en çok oylanan cevaplar işe yarıyor ama küçük bir sorun var, webpack tarayıcı konsoluna bir hata atıyor (Hata: webpackContextResolve'de './undefined' modülü bulunamıyor) ki bu çok hoş değil.

Bu yüzden biraz farklı çözdüm. Require ifadesinin içindeki değişkenle ilgili tüm sorun, need ifadesinin paketleme sırasında çalıştırılması ve bu ifadenin içindeki değişkenin yalnızca tarayıcıda uygulama yürütülmesi sırasında görünmesidir. Dolayısıyla webpack gerekli görüntüyü her iki şekilde de tanımsız olarak görür, çünkü derleme sırasında değişken yoktur.

Yaptığım şey, rastgele bir görüntüyü gerekli ifadesine yerleştirmek ve bu görüntüyü css'de saklamaktı, böylece kimse görmüyor.

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

Görüntü, Vuex aracılığıyla veri tabanındaki bilgilerin bir parçası olarak gelir ve hesaplanmış olarak bileşene eşlenir.

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

Bu bilgiler mevcut olduğunda, ilk resmi gerçek olanla değiştiriyorum

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

4

İşte çok basit cevap. : D

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

3

Bulunamayan görüntülere yardımcı olması için try catch block'u kullanabilirsiniz

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

Statik yol, yükleyici aracılığıyla bir modül bağımlılığı olarak Webpack tarafından çözülür. Ancak dinamik yol için kullanmanız gereken yolu çözmeniz gerekir. Daha sonra bir boole değişkeni ve üçlü ifade kullanarak görüntüler arasında geçiş yapabilirsiniz.

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

Ve elbette boolean değerini bir olay işleyicisi aracılığıyla değiştirin.


Teşekkürler bu çalışır :src="require(../assets/category_avatar/baby_kids.jpeg)"
Mohamed Raza

2

Vue.js vue-loader, dağıtımlar arasında farklılık gösterecek statik yollar (yerel, dev, bir barındırma platformu veya diğeri) hakkında endişelenmenize izin vermemeniz için derleme zamanında yolları yeniden yazmak / dönüştürmek üzere ayarlanan WebPack için bir yükleyici kullanır. , göreli yerel dosya sistemi yollarını kullanmanıza izin vererek . Ayrıca, varlık önbelleğe alma ve sürüm oluşturma gibi başka avantajlar da ekler (bunu muhtemelen gerçeksrc oluşturulan URL'yi ).

Normalde işleyen bir src'ye sahip olmak vue-loader / WebPack dinamik bir ifadeye ayarlanmış, çalışma zamanında değerlendirilecek bir src'ye , bu mekanizmayı atlatacak ve üretilen dinamik URL, gerçek dağıtım bağlamında geçersiz olacaktır (tam olarak nitelendirilmediği sürece, bu bir istisnadır) ).

Bunun yerine, requiredinamik ifadede bir işlev çağrısı kullanırsanız , vue-loader/ WebPack onu görecek ve olağan sihri uygulayacaktır.

Örneğin, bu işe yaramaz:

<img alt="Logo" :src="logo" />
computed: {
    logo() {
        return this.colorMode === 'dark'
               ? './assets/logo-dark.png'
               : './assets/logo-white.png';
    }
}

Bu işe yararken:

<img alt="Logo" :src="logo" />
computed: {
    logo() {
        return this.colorMode === 'dark'
               ? require('./assets/logo-dark.png')
               : require('./assets/logo-white.png');
    }
}

Bunu kendim öğrendim. Bir saatimi aldı ama ... yaşıyorsun, öğreniyorsun, değil mi? 😊


0

Benim için işe yarayan en iyi ve en kolay yol, bir API'den veri almamdı ..

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

getPic yöntemi dosyanın adı olan bir parametre alır ve dosyanın mutlak yolunu belki de sunucunuzdan basit dosya adıyla döndürür ...

İşte bunu kullandığım bir bileşene bir örnek:

<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

Ben de aynı problemle karşılaştım. Bu, "../assets/" öğesini "./assets/" olarak değiştirerek benim için çalıştı.

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

0

Buradaki tüm cevapları denedim ama benim için Vue2'de işe yarayan şey böyle.

<div class="col-lg-2" v-for="pic in pics">
   <img :src="require(`../assets/${pic.imagePath}.png`)" :alt="pic.picName">
</div>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.