Динамічні зображення Vue.js не працюють


90

У мене є випадок , коли в моєму Vue.jsз webpackвеб - додаток, мені потрібно , щоб відобразити динамічні зображення. Я хочу показати, imgде ім'я файлу зображень зберігається у змінній. Ця змінна - це computedвластивість, яка повертає Vuexзмінну сховища, яка заповнюється асинхронно beforeMount.

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

Однак це чудово працює, коли я просто роблю:

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

Мій випадок схожий на цю скрипку , але тут він працює з URL-адресою img, але в моєму з фактичними шляхами файлів це не працює.

Яким повинен бути правильний спосіб це зробити?


1
вирішено `<v-img: src =" require ( @/assets/+ items.image) "height =" 200px "> </v-img>` це також вирішило проблему
Мохамед Раза

Відповіді:


98

Я отримав це, працюючи за таким кодом

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

та в HTML:

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

Але не впевнений, чому мій попередній підхід не спрацював.


7
Відповідно до nickmessing: "Вираз усередині v-bind виконується під час виконання, псевдоніми webpack під час компіляції". github.com/vuejs/vue-loader/issues/896
antoine

@Grigio має підвищення хорошого до цієї відповіді: stackoverflow.com/a/47480286/5948587
samlandfried

1
Проблема полягала в тому, що шлях не існує. Весь додаток vue компілюється веб-пакетом в один сценарій (і зображення також перейменовуються нормально, використовуючи хеш вмісту). Використовуючи require.context, ви змушуєте файли переглядатися веб-пакетом і переходите до отриманого зображення. Перевірте робоче посилання в браузері, і ви зрозумієте, що я маю на увазі. Чудове рішення.
estani

Що робити, якщо я не хочу, щоб мої зображення знаходились у папці активів? Що робити, якщо вони існують лише у загальній папці веб-сайту, оскільки їх завантажують користувачі адміністративної області?
thinsoldier

привіт, я спробував це, але не вдалося, тоді я знайшов інше рішення, яке використовує шаблонні літерали. Це може працювати, і я хочу поділитися цим: stackoverflow.com/questions/57349167/…
лін

82

Ось скорочення, яке буде використовувати веб-пакет, тому вам не доведеться його використовувати require.context.

HTML:

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

Метод Vue:

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

І я вважаю, що перші 2 абзаци тут пояснюють, чому це працює? Ну.

Зверніть увагу, що корисно розміщувати фотографії улюбленців у підкаталозі, замість того, щоб вкладати їх у всі інші зображення. Подобається так:./assets/pets/


`<v-img: src =" require ( @/assets/+ items.image) "height =" 200px "> </v-img>` цей також вирішив проблему
Мохамед Раза

Це було єдине робоче рішення після
численних

38

Ви можете спробувати requireфункцію. подобається це:

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

Чому @потрібен цей символ?
шкода

1
@символ не потрібно, він часто відображає ваш srcкаталог при використанні Resolve | webpack (vue-cli це вже налаштовано.).
feng zhang

20

Існує ще один спосіб зробити це, додавши файли зображень до загальної папки замість ресурсів та отримавши доступ до них як статичні зображення.

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

Тут потрібно розмістити статичні зображення:

введіть тут опис зображення


Це спрацювало для мене, за винятком тегу alt, який я опустив v-bind
StefanBob

1
заощадило мені багато болю, я отримав дивну помилку: Не вдається знайти модуль «./undefined» , використовуючи вимагають, спасибі
Драккар

1
Я думаю, що це шлях, а не папка активів.
костюм вихідного дня

1
динамічне вимагання теж не працювало для мене в останньому Vue2
goodniceweb,

8

Найкраще - просто використовувати простий метод, щоб побудувати правильний рядок для зображення за заданим індексом:

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

тоді виконайте наступне всередині вашого v-for:

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

Ось JSFiddle (очевидно, що зображення не відображаються, тому я поклав зображення srcпоруч із ним):

https://jsfiddle.net/q2rzssxr/


Справді? Ось приклад із реальними зображеннями, які, здається, працюють нормально: jsfiddle.net/q2rzssxr/1
craig_h

Не знаю, чому, я змусив це працювати за кодом, який я написав в іншій відповіді. Ваш приклад навіть працює без цієї функції, дивіться тут: jsfiddle.net/9a6Lg2vd/1
Саураб

У моєму випадку, фото заселяється асинхронно з допомогою Vuex магазин, може бути, є що - то з цим робити, я намагався імітувати його, але не зробив роботу: jsfiddle.net/9a6Lg2vd/2
Saurabh

Мій випадок більше схожий на цей: jsfiddle.net/9a6Lg2vd/4 , але у моїх місцевих домашніх тварин дані потрапляють із виклику ajax, але зображення не відображаються.
Саураб

Це також працює: jsfiddle.net/9a6Lg2vd/5 , не впевнений, чому він не працює з файловими шляхами.
Саураб

5

Я також потрапив у цю проблему, і здається, що обидві найбільш прихильні відповіді працюють, але є крихітна проблема, webpack видає помилку в консолі браузера (Помилка: Не вдається знайти модуль './undefined' на webpackContextResolve), що не дуже приємно.

Тож я вирішив це дещо інакше. Вся проблема з оператором require в змінній усередині полягає в тому, що оператор require виконується під час групування, а змінна всередині цього оператора з'являється лише під час виконання програми у браузері. Отже, веб-пакет бачить потрібне зображення невизначеним у будь-якому випадку, оскільки під час компіляції ця змінна не існує.

Те, що я зробив, - це помістити випадкове зображення в оператор require і приховати це зображення в css, щоб ніхто його не бачив.

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

Зображення надходить як частина інформації з бази даних через Vuex і відображається на компонент як обчислюваний

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

Отже, коли ця інформація стає доступною, я поміняю початкове зображення реальним

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

4

Ось дуже проста відповідь. : D

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

3

Ви можете використовувати спробу catch block, щоб допомогти з не знайденими зображеннями

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

Статичний шлях вирішується Webpack як залежність модуля через завантажувач. Але для динамічного шляху вам потрібно використовувати require для вирішення шляху. Потім ви можете переключатися між зображеннями, використовуючи булеву змінну та трикутний вираз.

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

І звичайно перемикати значення логічного значення через якийсь обробник подій.


Дякую, це працює :src="require(../assets/category_avatar/baby_kids.jpeg)"
Мохамед Раза

0

ну найкращим і найпростішим способом, який працював у мене, був той, про який я отримував дані з API ..

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

метод getPic приймає один параметр, який є ім'ям файлу, і він повертає абсолютний шлях до файлу, можливо, із вашого сервера з простим ім'ям файлу ...

ось приклад компонента, де я використовував це:

<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

Я зіткнувся з тією ж проблемою. Це спрацювало для мене, змінивши "../assets/" на "./assets/".

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

-1

Спробуйте імпортувати подібне зображення, оскільки Webpack повинен знати про його залежність

    <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>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.