上传图片时如何在vue组件上自动更新图片?

Posted

技术标签:

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

我的 vue 组件是这样的:

<template>
    <section>
        ...
            <img class="media-object" :src="baseUrl+'/storage/banner/thumb/'+photo"   > 
        ...
    </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

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

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

【问题讨论】:

【参考方案1】:

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

<template>
<section>
    ...
        <img v-if="photoLink" class="media-object" :src="photoLink"   > 
        <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"   > 

【讨论】:

【参考方案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"   > 
</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" :  >
        </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 = '';
,

【讨论】:

以上是关于上传图片时如何在vue组件上自动更新图片?的主要内容,如果未能解决你的问题,请参考以下文章

新上传javascript时自动更新图片

Ant-design-vue中如何实现图片上传?

Ant-design-vue中如何实现图片上传?

Ant-design-vue中如何实现图片上传?

ckeditor粘贴word图片且图片自动上传组件

vue实现图片上传