Vue.js 3基于vue-class-component实现文件上传无法获取选中文件的解决方法
问题根因
你现在拿不到选中文件的核心原因是把ref的两个使用场景完全混用了,加上事件绑定逻辑有问题:
ref()是用来创建响应式值容器的API,作用是把普通值包装成可追踪的响应式引用,不是用来获取DOM元素、读选中文件的工具- 你代码里
this.file = ref(["file"]).value的写法完全没有实际意义,既没拿到DOM元素,也没读到文件数据,自然存不进this.file - 模板上的change事件绑定写法不对:你写的
v-on:change="onChangeFileUpload()"是直接调用空参数的方法,没有把原生事件传进去,就算方法里想读文件也拿不到数据源
修正方案
1. 模板调整
不需要改动核心结构,只需要修正change事件的传参逻辑,把原生事件对象传给处理方法,同时避免命名冲突:
<template> <h1>File Upload</h1> <div class="container"> <div> <label>File <input type="file" id="file" ref="fileInput" @change="onChangeFileUpload($event)" /> </label> <button @click="submitForm()">Upload</button> </div> </div> </template>
注意:把原来input上的ref="file"改成ref="fileInput",避免和你用来存选中文件的类属性file命名冲突
2. 逻辑代码调整
- 修正文件读取逻辑,从传入的事件对象中读取选中的File对象
- 去掉手动设置的
multipart/form-data请求头,交给axios根据FormData格式自动生成带边界标识的请求头,手动设置反而会导致后端无法解析文件
修正后的FileUploadTest.ts代码:
import { Options, Vue } from "vue-class-component"; import axios from "../../axios/index"; @Options({}) export default class FileUploadTest extends Vue { // 用来存选中的文件对象 protected file: File | null = null; submitForm() { // 没选文件的时候直接拦截 if (!this.file) return alert("请先选择要上传的文件"); const formData = new FormData(); formData.append('bytes', this.file); axios.post('https://localhost:44313/api/app/file/save', formData) .then(res => { console.log(res.data); }) .catch(() => { console.log('上传失败'); }); } onChangeFileUpload(e: Event) { const input = e.target as HTMLInputElement; // 读取选中的第一个文件,存到类属性里 this.file = input.files?.[0] ?? null; } };
其他可选实现方式
如果你想完全通过模板绑定的DOM ref读文件,不需要传事件对象,也可以在change方法里通过$refs获取DOM元素:
onChangeFileUpload() { const fileInputDom = this.$refs.fileInput as HTMLInputElement; this.file = fileInputDom.files?.[0] ?? null; }
这种写法的好处是不需要依赖事件对象,缺点是必须确保DOM元素已经挂载完成才能拿到引用。
内容的提问来源于stack exchange,提问作者Sukesh Chand
相关产品推荐
相关产品推荐

