用 ref 实现文件上传预览的核心是通过 ref 访问隐藏的 file input 元素,调用 click() 触发选择,再用 FileReader 读取文件生成 data URL 赋值给 previewUrl 用于 img 标签展示,并可复用 file 对象上传至服务器。

用 ref 实现文件上传预览,核心是绕过表单提交、直接读取本地文件内容,并将结果绑定到视图。Vue 中的 ref 提供对原生 DOM 元素的直接访问能力,正好用来触发隐藏的 <input type="file">,并监听其变化。
1. 创建隐藏 file input 并用 ref 绑定
不暴露原生文件选择框,而是用自定义按钮触发;通过 ref 拿到 input DOM 实例,调用 .click() 模拟点击:
- 在模板中添加
<input ref="fileInput" type="file" accept="image/*" class="hidden"> -
class="hidden"用 CSS 隐藏(如display: none或position: absolute; left: -9999px) - 在组件 setup 中声明
const fileInput = ref(null),确保能访问到该 DOM 节点
2. 读取文件并生成预览 URL
用户选中文件后,用 FileReader 同步读取为 data URL,赋值给响应式变量用于 img 标签展示:
-
handleFileChange中先判断event.target.files.length > 0 - 取第一个文件:
const file = event.target.files[0] - 检查类型是否为图片(可选):
if (!file.type.startsWith('image/')) return - 新建
const reader = new FileReader(),监听reader.onload,把reader.result赋给previewUrl(一个ref或reactive属性) - 最后调用
reader.readAsDataURL(file)
3. 触发上传逻辑(可选)
预览只是第一步,后续常需上传到服务器。此时可复用已选的 file 对象:
立即学习“前端免费学习笔记(深入)”;
- 封装一个
uploadFile(file)方法,使用FormData构建请求体 - 例如:
const formData = new FormData(); formData.append('file', file); - 配合
axios.post('/upload', formData, { headers: { 'Content-Type': 'multipart/form-data' } }) - 注意:不要在
onload回调里上传,避免因读取延迟导致 file 对象失效;应在change事件中立即获取并传入上传函数
4. 清除与重置功能
用户可能想换图或取消,需提供清除预览和重置 input 的能力:
- 点击“清除”时,将
previewUrl设为空字符串,同时手动清空fileInput.value = ''(否则再次点击按钮不会触发 change 事件) - 也可封装一个
resetInput()方法统一处理 - 若支持多图,可用数组管理多个
previewUrl,每次新增 push,清除则 splice 或 filter
整个过程不依赖第三方库,纯 Vue + 原生 API 即可完成。关键是理解 ref 是桥梁,FileReader 是转换器,而 previewUrl 是连接 DOM 和响应式的纽带。


















