【问题标题】:Vue.js dynamic images not workingVue.js 动态图像不起作用
【发布时间】:2017-03-22 08:24:48
【问题描述】:

我有一个案例,在我的 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,但在我的实际文件路径中,它不起作用。

正确的做法应该是什么?

【问题讨论】:

  • 已解决 ` ` 这个一个也解决了问题

标签: javascript html vue.js vuejs2


【解决方案1】:
<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>

【讨论】:

    【解决方案2】:

    我也遇到过这个问题。

    试试看:

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

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

    【讨论】:

      【解决方案3】:

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

      **我也用过toLowerCase()方法

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

      【讨论】:

        【解决方案4】:

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

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

        @ 符号指向src 目录。

        来源:Vue URL transfrom rules

        【讨论】:

        • 为什么需要@ 符号?
        • @ 符号不是必需的,当使用Resolve | webpack 时,它通常代表您的src 目录(vue-cli 已经配置了这个。)。
        【解决方案5】:

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

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

        【讨论】:

          【解决方案6】:

          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');
              }
          }
          

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

          【讨论】:

            【解决方案7】:
            <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)"
            【解决方案8】:

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

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

            【讨论】:

              【解决方案9】:

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

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

              【讨论】:

                【解决方案10】:

                我也遇到了这个问题,似乎两个最受好评的答案都有效,但有一个小问题,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;
                  }
                }
                

                【讨论】:

                  【解决方案11】:

                  您可以使用 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
                  },
                  

                  【讨论】:

                    【解决方案12】:

                    这是 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 中的前两段解释了为什么会这样?很好。

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

                    【讨论】:

                    • ` `这个也解决了问题
                    • 这是经过大量尝试后唯一可行的解​​决方案..
                    • 这里每个答案的秘密是他们在require方法中有../assets,查看stackoverflow.com/questions/57349167/…了解更多详情
                    • 这是唯一对我有用的解决方案
                    【解决方案13】:

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

                    【讨论】:

                      【解决方案14】:

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

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

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

                      【讨论】:

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

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

                        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 看到文件并解析到生成的图像。检查浏览器中的工作链接,你会明白我的意思。很好的解决方案。
                      • 如果我不希望我的图片出现在 assets 文件夹中怎么办?如果它们只存在于网站的公用文件夹中,因为它们是由管理区域的用户上传的呢?
                      • 你好,我试过这个但失败了,然后我找到了另一个使用模板文字的解决方案。它可以工作,我想分享这个:stackoverflow.com/questions/57349167/…
                      【解决方案16】:

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

                      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,不知道为什么它不适用于文件路径。
                      猜你喜欢
                      • 2021-06-01
                      • 2019-12-12
                      • 2019-04-14
                      • 1970-01-01
                      • 2019-03-15
                      • 1970-01-01
                      • 2015-10-18
                      • 2019-03-16
                      • 1970-01-01
                      相关资源
                      最近更新 更多