Renaming/removing 上传的文件 - Vue.js

Renaming/removing uploaded files - Vue.js

要求是在将文件上传到系统之前重命名文件。所以我厌倦了使用 v-model 但失败了。所以我想出了以下效果很好,只是我无法保留我的输入文本值。 preventdefault 不工作。

Here I uploaded 3 images and rename them as First, Second and Third.

<div>
    <input type="file" @change="addFile" multiple>Choose file
</div>

<div v-if="selectedFiles && selectedFiles.length>0">
       <div v-for="(item, index) in selectedFiles">
            <span>{{ item.name }}</span>
            <input type="text" v-model="" placeholder="Rename File" @change="renameFile(item,event)"/>
            <button @click="removeFile(event,item,index)"></button>                                    
        </div>
 </div>   
 <button @click="uploadDrawings">Upload Files</button>                                        
data: {
      selectedFiles: [],
      renameFiles: [],
      finalFiles: [], 
},
methods: {

    addFile(event) {
        _.each(Array.from(event.target.files), function (file) {

            var existed = _.find(app.selectedFiles, function (item) {
                return item.name == file.name;
            });

            if (!existed) {
                app.selectedFiles.push(file);
            }
        });
    },
    renameFile(item, event) {
        if (app.renameFiles.filter(x => x.oldName == item.name).length > 0) {
            var objIndex = app.renameFiles.findIndex(x => x.oldName == item.name);
            app.renameFiles[objIndex].newName = event.target.value;
        }
        else {
            app.renameFiles.push({
                oldName: item.name,
                newName: event.target.value
            })
        }
    },
    removeFile(e,item, index) {
        e.preventDefault(); // while removing an item, the text value changes.
        app.selectedFiles.splice(index, 1);
        var objIndex = app.renameFiles.findIndex(x => x.oldName == item.name);
        app.renameFiles.splice(objIndex, 1);
    },

    uploadDrawings() {
       app.isLoading = true;
       if (app.selectedFiles.length == 0) {
         return;
     }

     _.each(app.selectedFiles, function (item) {
          var blob = item.slice(0, item.size, 'image/jpg');
          var name = app.renameFiles.filter(x => x.oldName == item.name);
          app.finalFiles.push(new File([blob], name[0].newName + '.jpeg', { type: 'image/jpg' }));
});
}

因此,在从上到下移除项目时,文本框不会保留其值。 First 分配给 091646

但是,finalFiles 具有正确的命名文件。只是文本框有问题。

请帮我保留文本框的值。 提前致谢。

缺少 keys

v-for 中的项目未在您的标记中明确键入,因此 Vue 会自动通过索引对它们进行键入。作为渲染优化,Vue 重用由键标识的现有元素。当一个项目被添加到列表中间或从中间删除时,这可能会导致问题,其中周围的项目采用与其新索引相等的新键。

解决方案

使用 唯一 ID(不等于 index)将 key 属性应用于每个 v-for 项目。在这种情况下,index 与文件名结合就足够了:

<div v-for="(item, index) in selectedFiles" :key="index + item.name">

缺少 v-models

当模板为 re-rendered 时(从列表中间删除项目时发生),文本框将失去其值。这是因为它们没有绑定模型。

解决方案

更新 renameFiles[] 以仅存储字符串(而不是对象),其中每个字符串对应于 selectedFiles[] 相同索引 中的一个文件。这将避免整个方法中的文件查找代码,因此代码将简化为:

export default {
  ⋮
  methods: {
    addFile(event) {
      this.selectedFiles = Array.from(event.target.files)
    },
    removeFile(e, item, index) {
      this.selectedFiles.splice(index, 1)
      this.renameFiles.splice(index, 1)
    },
    ⋮
  },
}

该更改还允许在重命名字符串的 <input> 上使用 renameFiles[] 作为 v-model

<input type="text" v-model="renameFiles[index]" placeholder="Rename File" />

demo