如何使用vue.js取消要上载的预览图像和文件名

时间:2018-04-04 18:32:52

标签: javascript vue.js

我正在构建一个可以使用vue.js一次上传多个图片的应用。在文件输入的@change事件中(当我选择要上载的文件时),我想要所选图像的预览和名称,然后是一个取消单个文件的按钮。一切正常。但是,当我尝试使用按钮取消任何图像时,只有名称被删除,图像仍然存在。有人可以指导我纠正我做错了什么。问题似乎与我的cancelImage方法有关。 我的模板:

<div class="form-group">
  <textarea name="body" class="form-control" v-model="body"></textarea>
</div>
<div class="form-group">
  <label class="control-label">Files
  <input type="file" ref="files" accept="image/*" multiple="multiple" @change="selectFiles">
  </label>
</div>
<div v-for="(file, key) in files">
    <img class="preview" v-bind:ref="'image' +parseInt( key )" /> 
    &nbsp{{ file.name }}
    <button type="button" class="btn btn-danger" @click.prevent="cancelImage(file, key)"> X </button>
</div>
<div class="form-group">
    <button @click.prevent="addFiles" class="btn btn-default">Add Files</button>
</div>
<div class="form-group">
    <button type="button" class="btn btn-primary btn-block" @click.prevent="upload">Upload</button>
</div>

然后是我的剧本:

export default {
      data(){
        return {
          body: '',
          files: [],
          form: new FormData()
        }
      },
      methods: {
        uploadFiles(e){
          let selectedFiles = e.target.files;
          let vm = this;
          for (let i=0; i < selectedFiles.length; i++){
            vm.files.push(selectedFiles[i]);
          }
          this.imagePreview();
          console.log(this.files)
        },
        imagePreview(){
          let vm = this;
          for (let i=0; i<vm.files.length; i++){
            let reader = new FileReader();

            reader.addEventListener('load', function(){
              vm.$refs['image' + parseInt( i )][0].src = reader.result;
            }.bind(vm), false);
            reader.readAsDataURL(vm.files[i]);
          }
        },
        addFiles(){
          this.$refs.files.click();
        },
        cancelImage(file){
           let index = this.files.indexOf(file);
           this.files.splice(index, 1);
        }
     }
  }

1 个答案:

答案 0 :(得分:1)

使用v-for数组时,可以传递2个参数。第一个是迭代的项目,第二个是该项目的索引。所以现在,这个:

<div v-for="(file, key) in files">
    <img class="preview" v-bind:ref="'image' +parseInt( key )" /> 
    &nbsp{{ file.name }}
    <button type="button" class="btn btn-danger" @click.prevent="cancelImage(file, key)"> X </button>
</div>

可能没有完全按照您的想法行事。 file是您正在迭代的项目(推送formData),而key实际上是files数组中项目的索引。通常,v-for中的key用于向每个元素添加唯一标识符,以帮助Vue知道哪个元素是哪个元素。您可以使用:key属性(类似file.id或类似的prop作为唯一ID)。所以尝试这样的事情:

HTML:

<div v-for="(file, index) in files" :key="file.name"> // This is a terrible key, but I am not sure what properties exist on your formData objects.
    <img class="preview" v-bind:ref="'image' + index" /> 
    &nbsp{{ file.name }}
    <button type="button" class="btn btn-danger" @click.prevent="cancelImage(index)"> X </button>
</div>

JS:

cancelImage(index){
  this.files.splice(index, 1);
}

由于v-for正在为数组中的每个元素创建一个按钮,这会将索引传递给cancelImage方法,并允许您删除该特定元素,而无需先“查找”文件的索引

修改:从file方法中删除了cancelImage,因为只需要索引。