ChatGPT解决这个技术问题 Extra ChatGPT

Vue.js 动态图像不起作用

我有一个案例,在我的 Vue.jswebpack 网络应用程序中,我需要显示动态图像。我想显示 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">

我的情况与此 fiddle 类似,但在这里它适用于 img URL,但在我的实际文件路径中,它不起作用。

正确的方法应该是什么?

解决了 ` <v-img :src="require(@/assets/ + items.image)" height="200px"></v-img>`这个也解决了问题

S
Saurabh

我通过以下代码得到了这个工作

  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>

但不知道为什么我之前的方法不起作用。


根据 nickmessing 的说法:“v-bind 中的表达式在运行时执行,webpack 别名在编译时执行。” github.com/vuejs/vue-loader/issues/896
@Grigio 对此答案进行了很好的改进:stackoverflow.com/a/47480286/5948587
问题是路径不存在。整个 vue 应用程序由 webpack 编译成单个脚本(并且图像也正常重命名,使用内容的哈希)。使用 require.context,你可以强制 webpack 看到文件并解析到生成的图像。检查浏览器中的工作链接,你会明白我的意思。很好的解决方案。
如果我不希望我的图像位于资产文件夹中怎么办?如果它们仅存在于网站的公用文件夹中,因为它们是由管理区域的用户上传的,该怎么办?
你好,我试过这个但失败了,然后我找到了另一个使用模板文字的解决方案。它可以工作,我想分享这个:stackoverflow.com/questions/57349167/…
C
Cody G

这是 webpack 将使用的简写,因此您不必使用 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)
}

而且我发现 here 中的前 2 段很好地解释了为什么会这样?

请注意,将您的宠物图片放在子目录中是个好主意,而不是将其与所有其他图像资产一起放入。像这样:./assets/pets/


` <v-img :src="require(@/assets/ + items.image)" height="200px"></v-img>`这个也解决了问题
这是经过大量尝试后唯一可行的解决方案..
这里每个答案的秘诀是他们在 require 方法中有 ../assets,请查看 stackoverflow.com/questions/57349167/… 了解更多详细信息
这是唯一对我有用的解决方案
J
Jesse Reza Khorasanee

您可以尝试 require 功能。像这样:

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

@ 符号指向 src 目录。

来源:Vue URL transfrom rules


为什么需要那个 @ 符号?
@ 符号不是必需的,它在使用 Resolve | webpack 时通常代表您的 src 目录(vue-cli 已经配置了这个。)。
R
Rukshan Dangalla

还有另一种方法是通过将图像文件添加到公共文件夹而不是资产并将它们作为静态图像访问。

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

这是您需要放置静态图像的地方:

https://i.stack.imgur.com/H3uSs.png


这对我有用,除了 alt 标签我省略了 v-bind
为我节省了很多痛苦,我得到了奇怪的错误:使用 require 找不到模块'./undefined',谢谢
我认为这是要走的路,而不是资产文件夹。
在最新的 Vue2 中,动态要求对我也不起作用
Require 在 Vue3 中也不适用于我,但这是一个了不起的解决方案
c
craig_h

最好的办法是使用一种简单的方法在给定索引处为图像构建正确的字符串:

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
不知道为什么,我通过我在另一个答案中编写的代码让它工作了。您的示例甚至可以在没有此功能的情况下工作,请参见此处:jsfiddle.net/9a6Lg2vd/1
就我而言,图片是使用 Vuex 商店异步填充的,可能与它有关,我试图模拟它,但没有奏效:jsfiddle.net/9a6Lg2vd/2
我的情况更像这样: jsfiddle.net/9a6Lg2vd/4 ,但是在我的本地宠物中,从 ajax 调用中获取了数据,但图像没有得到渲染。
这也有效:jsfiddle.net/9a6Lg2vd/5,不确定为什么它不适用于文件路径。
A
Alonad

我也遇到了这个问题,似乎两个最受好评的答案都有效,但有一个小问题,webpack 在浏览器控制台中抛出一个错误(错误:在 webpackContextResolve 找不到模块'./undefined'),这不是很好。

所以我用不同的方式解决了它。 require 语句中的变量的整个问题是,require 语句是在捆绑期间执行的,而该语句中的变量仅在浏览器中的应用程序执行期间出现。所以 webpack 认为所需的图像是未定义的,因为在编译期间该变量不存在。

我所做的是将随机图像放入 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;
  }
}

P
Paul-Sebastian

Vue.js 使用 vue-loader,一个用于 WebPack 的加载器,它设置为在编译时重写/转换路径,以便让您不必担心部署(本地、开发、一个托管平台或另一个),通过允许您使用相对本地文件系统路径。它还增加了其他好处,例如资产缓存和版本控制(您可以通过检查正在生成的实际 src URL 看到这一点)。

因此,将通常由 vue-loader/WebPack 处理的 src 设置为在运行时评估的动态表达式,将绕过此机制,并且生成的动态 URL 在实际部署的上下文中将是无效的(除非它是完全限定的,这是一个例外)。

相反,如果您在动态表达式中使用 require 函数调用,vue-loader/WebPack 将看到它并应用通常的魔法。

例如,这不起作用:

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

虽然这会起作用:

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

我自己才发现这件事。花了我一个小时,但是……你活着,你学习,对吧? 😊


R
Ron16
<img src="../assets/graph_selected.svg"/>

静态路径由 Webpack 通过 loader 解析为模块依赖。但是对于动态路径,您需要使用 require 来解析路径。然后,您可以使用布尔变量和三元表达式在图像之间切换。

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

当然,通过一些事件处理程序来切换布尔值。


谢谢你这工作:src="require(../assets/category_avatar/baby_kids.jpeg)"
P
Prashant Pandey
<div
    v-for="(data, i) in statistics"
    :key="i"
    class="d-flex align-items-center"
  >
    <img :src="require('@/assets/images/'+ data.title + '.svg')" />
    <div class="ml-2 flex-column d-flex">
      <h4 class="text-left mb-0">{{ data.count }}</h4>
      <small class="text-muted text-left mt-0">{{ data.title }}</small>
    </div>
  </div>

G
Gabriel Fernandez

您可以使用 try catch 块来帮助处理未找到的图像

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

D
Diamond

这是非常简单的答案。 :D

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

l
leipzy

在这里尝试了所有答案,但在 Vue2 上对我有用的是这样。

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

D
Dip Chowdhury

当我使用 Gridsome 时,这种方式对我有用。

**我也用过 toLowerCase() 方法

      <img
        :src="
          require(`@/assets/images/flags/${tournamentData.address.country_name.toLowerCase()}.svg`)
        "
      />

D
Denkhis

我也遇到过这个问题。

试试看:

computed {
    getImage () {
        return require(`../assets/images/${imageName}.jpg`) // the module request
    }
}

这是一篇很好的文章,阐明了这一点:https://blog.lichter.io/posts/dynamic-images-vue-nuxt/


u
user8453321

对我来说最好和最简单的方法就是我从 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>

B
Bex

我遇到了同样的问题。通过将“../assets/”更改为“./assets/”,这对我有用。

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

A
Arslan Ameer

到今天为止,使用 VUE 3 + Typescript & composition API,我所做的是在 try catch 中包装 require 函数来处理崩溃。

computed: {
    getImage() {
        let imgSrc = "";
        try {
            imgSrc = require(`../assets/weather-widget-icons/ww-icon-${this.weatherForecast.main.toLowerCase()}.svg`);
        } catch (error) {
            console.error(`Image '../assets/weather-widget-icons/ww-icon-${this.weatherForecast.main.toLowerCase()}.svg' not found!`);
        }
        return imgSrc;
    }
}

并在图像标签中调用此函数:

<div class="weather-icon">
    <img :src="getImage" :alt="weatherForecast.main" />
</div>