【问题标题】:How can I update image automatic on vue component when I upload the image?上传图片时如何在vue组件上自动更新图片?
【发布时间】:2018-08-15 05:53:45
【问题描述】:

我的 vue 组件是这样的:

<template>
    <section>
        ...
            <img class="media-object" :src="baseUrl+'/storage/banner/thumb/'+photo" alt="" width="64" height="64"> 
        ...
    </section>
</template>
<script>
    export default {
        props: ['banners'],
        data() {
            return {
                baseUrl: App.baseUrl,
                bannerId: this.banners.id,
                photo: this.banners.photo // result : chelsea.png
            }
        },
        methods: {
            onFileChange(e) {
                let files = e.target.files,
                    reader = new FileReader(),
                    formData = new FormData(),
                    self = this

                formData.append('file', files[0])
                formData.append('banner_id', this.bannerId)

                axios.post(window.App.baseUrl+'/admin/banner/upload-image',
                formData,
                {
                    headers: {
                        'Content-Type': 'multipart/form-data'
                    }
                }
                ).then(function(response) {
                    if(response.data.status == 'success') {
                        self.photo = response.data.fileName // result : chelsea.png
                    }
                })
                .catch(function(error) {
                    console.log('FAILURE!!')
                })
            },
            ...
        }
    }
</script>

:src 的结果:\my-app\storage\app\public\banner\thumb\chelsea.png

当我上传图片时,它会调用 onFileChange 方法。并且进程上传将在后端继续。它成功上传到文件夹中。并且响应将返回相同的文件名。所以response.data.fileName的结果是chelsea.png

我的问题是:上传图片时不会自动更新图片。当我刷新页面时,图像更新了

为什么我上传图片时图片没有自动更新/更改?

【问题讨论】:

    标签: javascript vue.js vuejs2 image-uploading vue-component


    【解决方案1】:

    尝试绑定完整照片的路径:

    <template>
    <section>
        ...
            <img v-if="photoLink" class="media-object" :src="photoLink" alt="" width="64" height="64"> 
            <p v-text="photoLink"></p>
        ...
    </section>
    </template>
    <script>
    export default {
        props: ['banners'],
        data() {
            return {
                baseUrl: App.baseUrl,
                bannerId: this.banners.id,
                photo: this.banners.photo, // result : chelsea.png
                photoLink: App.baseUrl + '/storage/banner/thumb/' + this.banners.photo 
            }
        },
        methods: {
            onFileChange(e) {
                let files = e.target.files,
                    reader = new FileReader(),
                    formData = new FormData(),
                    self = this
    
                formData.append('file', files[0])
                formData.append('banner_id', this.bannerId)
    
                axios.post(window.App.baseUrl+'/admin/banner/upload-image',
                formData,
                {
                    headers: {
                        'Content-Type': 'multipart/form-data'
                    }
                }
                ).then(function(response) {
                    if(response.data.status == 'success') {
                        // self.photo = response.data.fileName // result : chelsea.png
                        console.log('>>>INSIDE SUCCESS');
                        self.photoLink = self.baseUrl + '/storage/banner/thumb/' + response.data.fileName;
                    }
                })
                .catch(function(error) {
                    console.log('FAILURE!!')
                })
            },
            ...
        }
    }
    

    【讨论】:

    • 你能通过打印console.log('&gt;&gt;&gt;INSIDE SUCCESS');确保'success'里面的代码正在执行吗?还有&lt;p v-text="photoLink"&gt;&lt;/p&gt; 正在更新新的photoLink?
    • console.log('&gt;&gt;&gt;INSIDE SUCCESS'); 的结果显示在控制台上。但是图片没有更新
    • &lt;p v-text="photoLink"&gt;&lt;/p&gt; 更新了吗?
    • 是的。它正在更新。但是图片仍然没有更新
    • 这似乎是因为文件名与响应中的文件名相同。文件名:chelsea.png。如果文件名与响应不同,它可以工作。但是这里我希望文件名是一样的
    【解决方案2】:

    只需使用计算属性,sn-p 下面使用getImageUrl 来获取更新的路径。我添加了按钮来触发所提供数据的模拟变化。

    new Vue({
    	el: "#app",
      data: {
      	baseUrl: 'baseURl', //dummy
        bannerId: '', //dummy
        photo: 'initPhoto.png' // dummy
      },
      computed: {
      	getImageUrl: function() {
        	return this.baseUrl + '/storage/banner/thumb/' + this.photo;
        }
      },
      methods: {
      	mimicOnChange: function() {
        	this.photo = "chelsea.png"
        }
      }
    })
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.13/dist/vue.js"></script>
    <div id="app">
     <span>{{ getImageUrl }}</span>
     <br/>
     <button @click="mimicOnChange">
     On change trigger
     </button>
    </div>

    在您上面的代码中,只需将计算直接用于您的 src 属性:

    <img class="media-object" :src="getImageUrl" alt="" width="64" height="64"> 
    

    【讨论】:

      【解决方案3】:

      您的图像由浏览器缓存。尝试向图像添加任何标签,例如: chelsea.png?t=

      【讨论】:

      • 是的,有时它会给我相同的图像,但刷新后它改变了,我如何在不重命名图像本身的情况下修复它?
      • 通常,后端会为我们提供 MIME 类型的图像路径,例如 /image/12334。不返回 image.png。
      【解决方案4】:

      我通过执行以下操作修复了它,请注意我在照片 url 的末尾添加了一个名为 rand 的变量用于缓存清除。当您从服务器获得正确响应时,只需将该变量更改为唯一的值(在本例中为时间戳),瞧!您的图像将刷新。

      <template>
          <img class="media-object" :src="baseUrl+'/storage/banner/thumb/'+photo + '?rand=' + rand" alt="" width="64" height="64"> 
      </template>
      <script>
          export default {
              data() {
                 return {
                     rand: 1
                 }
              },
              methods: {
                  onFileChange(e) {
                      ...
                      axios.post(url,formData).then(function(response) {
                          if(response.data.status == 'success') {
                              self.rand = Date.now()
                          }
                      })
                  },
              ...
          }
      
          }
      

      【讨论】:

        【解决方案5】:

        上面提供的答案是计算属性,因为这些属性被设计为响应式的,但是当涉及到异步时,最好使用 promises / observables。但是,如果您决定不使用并且仍然遇到问题,那么您可以使用加载属性,例如下面示例中的 loading 属性来操作 DOM,即在您启动异步 (axios) 时使用 v-if 删除 DOM .获取并设置图像,然后使用this.loading = true; 恢复 DOM 元素。这会强制渲染 DOM,从而强制计算属性。

        
        <template>
            <section>
                <div v-if="!loading">
                    <img class="media-object" :src="getPhoto" :alt="getAlt" width="64" height="64">
                </div>
                <div v-if="loading">
        <!--            OR some spinner-->
                    <div>Loading image</div>
                </div>
            </section>
        </template>
        <script>
            export default {
                props: ['banners'],
                data() {
                    return {
                        loading: false,
                        baseUrl: App.baseUrl,
                        bannerId: this.banners.id,
                        photo: {} // result : chelsea.png
                    }
                },
                computed: {
                    getPhoto() {
                        return App.baseUrl + '/storage/banner/thumb/' + this.photo.fileName;
                    },
                    getAlt() {
                        return photo.alt;
                    },
                },
                methods: {
                    onFileChange(e) {
                        let files = e.target.files,
                            reader = new FileReader(),
                            formData = new FormData(),
                            self = this
        
                        // Set loading to true 
                        this.loading = true;
        
                        formData.append('file', files[0])
                        formData.append('banner_id', this.bannerId)
        
                        axios.post(window.App.baseUrl+'/admin/banner/upload-image',
                            formData,
                            {
                                headers: {
                                    'Content-Type': 'multipart/form-data'
                                }
                            }
                        ).then(function(response) {
                            if(response.data.status == 'success') {
                                self.photo = response.data.fileName // result : chelsea.png
                                this.loading = false;
                            }
                        })
                            .catch(function(error) {
                                console.log('FAILURE!!')
                            })
                    },
                    ...
                }
            }
        </script>
        
        
        

        【讨论】:

          【解决方案6】:

          我遇到了同样的问题,在输入后插入相同的图像不会触发任何操作。我通过清除输入来修复它。

          clearInput(e) {
            e.target.value = '';
          },
          

          【讨论】:

            猜你喜欢
            • 2021-05-07
            • 2017-12-16
            • 2019-04-18
            • 1970-01-01
            • 2022-08-14
            • 2011-07-08
            • 2016-09-22
            • 2019-05-31
            • 2020-09-04
            相关资源
            最近更新 更多