首页 > 解决方案 > 在 Vue 组件中自动重新加载图像

问题描述

我有一个用于货物操作的简单组件。在这个组件中,我可以创建商品并更改它们的图像。当我更改某个商品的图像时,后端应用程序会执行替换具有相同名称的现有图像,因此图像 URL 不会更改。因此,在我刷新页面之前,页面上的图像不会重新加载。

获得成功的服务器响应后,如何强制重新加载图像?

那是很好的组件来源:

<template>
  <div class="container">
    <h3 class="mt-5">Goods</h3>

    <div class="row mt-5">
      <div class="col-md-12">
        <div class="card">
          <div class="card-header align-middle">
            <div class="card-tools">
              <button class="btn btn-success btn-sm" v-b-modal.create-good-modal>Add</button>
            </div>
          </div>
          <div class="card-body table-responsive p-0">
            <table class="table table-hover text-center">
              <thead>
                <tr>
                  <th>ID</th>
                  <th>Image</th>
                  <th>Name</th>
                </tr>
              </thead>
              <tbody>
                <tr v-for="good in goods" :key="good.id">
                  <td class="align-middle">{{ good.id }}</td>
                  <td class="align-middle">
                    <img class="img-thumbnail" width="60" :src="goodImageUrl(good.image)"
                      v-b-modal.change-good-image-modal @click="changeGoodImage(good.id)" />
                  </td>
                  <td class="align-middle">{{ good.name }}</td>
                </tr>
              </tbody>
            </table>
          </div>
        </div>
      </div>
    </div>
    <b-modal ref="createGoodModal" id="create-good-modal" title="New good" hide-footer @show="resetCreateGoodModal"
      @hide="resetCreateGoodModal">
      <b-form @submit="createGood" class="w-100">
        <b-form-group id="form-create-good-name-group" label="Name" label-for="form-create-good-name-input">
          <b-form-input id="form-create-good-name-input" type="text" v-model="createGoodForm.name" required
            placeholder="Good name">
          </b-form-input>
        </b-form-group>
        <b-form-group id="form-create-good-image-group">
          <b-form-file v-model="createGoodForm.image" required :state="Boolean(createGoodForm.image)"
            placeholder="Choose good image">
          </b-form-file>
          <div class="mt-3">Selected image: {{ createGoodForm.image ? createGoodForm.image.name : '' }}</div>
        </b-form-group>
        <b-button type="submit" variant="primary">Create</b-button>
      </b-form>
    </b-modal>
    <b-modal ref="changeGoodImageModal" id="change-good-image-modal" title="Change good image"
      @hide="resetChangeGoodImageModal" hide-footer>
      <b-form @submit="updateGoodImage" class="w-100">
        <b-form-group id="form-change-good-image-group">
          <b-form-file v-model="changeGoodImageForm.image" required :state="Boolean(changeGoodImageForm.image)"
            placeholder="Choose good image">
          </b-form-file>
          <div class="mt-3">Selected file: {{ changeGoodImageForm.image ? changeGoodImageForm.image.name : ''
                      }}
          </div>
        </b-form-group>
        <b-button type="submit" variant="primary">Save</b-button>
      </b-form>
    </b-modal>
  </div>
</template>

<script>
  import {objectToFormData} from "object-to-formdata";
    export default {
    data() {
        return {
    goods: [],
          createGoodForm: new Form({
    name: "",
            image: null
          }),
          changeGoodImageForm: new Form({
    id: {},
            image: null
          })
        };
      },
      methods: {
    getGoods() {
    axios
      .get("goods/list")
      .then(response => {
        this.goods = response.data;
      })
      .catch(error => {
        console.error(error);
      });
        },
        createGood() {
    this.createGoodForm
      .post("goods", {
        transformRequest: [
          function (data, headers) {
            return objectToFormData(data);
          }
        ]
      })
      .then(() => {
        this.$refs.createGoodModal.hide();
        this.getGoods();
      })
      .catch(error => {
        console.log(error);
      });
        },
        changeGoodImage(id) {
    this.changeGoodImageForm.id = id;
        },
        updateGoodImage() {
    this.changeGoodImageForm
      .post("goods/" + this.changeGoodImageForm.id + "/image", {
        transformRequest: [
          function (data, headers) {
            return objectToFormData(data);
          }
        ]
      })
      .then(() => {
        this.$refs.changeGoodImageModal.hide();
        this.getGoods();
      })
      .catch(error => {
        console.log(error);
      });
        },
        goodImageUrl(filename) {
          return "http://127.0.0.1:8098/api/img/goods/" + filename;
        },
        resetCreateGoodModal() {
    this.createGoodForm.reset();
        },
        resetChangeGoodImageModal() {
    this.changeGoodImageForm.reset();
        }
      },
      created() {
    this.getGoods();
      }
    };
</script>

标签: vue.jsvuejs2

解决方案


我的建议只是将随机缓存破坏器附加到图像 url - 服务器将忽略的查询参数将强制浏览器获取新图像。这假设您的后端不会拒绝请求,但大多数时候这种方法有效。类似的东西/myimage.png?cacheBuster=<somethingRandom>请注意,在下面的代码段中,实际上不会加载新的猫图像,因为该服务器每次都没有新图像。这只是一个演示。

为了减少技术债务并帮助记录/调试,我建议做一些额外的工作并让您的 api 返回一个您可以附加的新图像版本,而不仅仅是粗略的缓存崩溃。但这是一个更大的项目。例子/myimage.png?version=2

const originalSource = 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/69/June_odd-eyed-cat_cropped.jpg/120px-June_odd-eyed-cat_cropped.jpg';
var app = new Vue({
  el: '#app',
  data() {
    return {
      imageSource: originalSource
    }
  },
  methods: {
    bustThatCache() {
      this.imageSource = `${originalSource}?cacheBust=${Math.random()}`
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <p>Image Src:{{imageSource}}</p>
  <img :src="imageSource"></img>
  <button @click="bustThatCache">Load new image</button>
</div>


推荐阅读