ReactJS结合Firebase上传图片时如何显示上传进度提示?
实现方法
Firebase Storage的上传任务原生支持进度监听,配合全屏遮罩+页面离开拦截就能实现你要的效果,不需要引入额外依赖。
1. 添加上传状态视觉提示
先在页面中插入一个默认隐藏的全屏遮罩层,上传开始时显示,上传结束(成功/失败)时隐藏,层内放置加载图标、进度条、进度文字即可。因为遮罩层级最高,会覆盖页面所有可点击元素,自然能阻止用户上传过程中点击页面内的按钮、链接跳转。
基础遮罩结构示例:
<div id="upload-mask" style="display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.6); z-index: 9999; flex-direction: column; justify-content: center; align-items: center;"> <!-- 转圈加载图标,可自行替换成项目里的加载组件 --> <div class="spin-icon" style="width: 40px; height: 40px; border: 4px solid #fff; border-top-color: transparent; border-radius: 50%; animation: spin 1s linear infinite;"></div> <div style="width: 300px; height: 8px; background: #eee; border-radius: 4px; margin: 20px 0; overflow: hidden;"> <div id="progress-bar" style="height: 100%; width: 0; background: #2563eb; transition: width .2s;"></div> </div> <p id="progress-text" style="color: #fff; margin: 0;">上传中 0%</p> </div> <style> @keyframes spin {to {transform: rotate(360deg);}} </style>
2. 修改上传逻辑,监听进度+拦截页面关闭
用Firebase上传任务自带的state_changed观察者实时获取上传进度,同时监听浏览器的beforeunload事件,阻止用户上传过程中刷新、关闭标签页、跳转到外部站点。
修改后的完整上传代码:
// 提前获取遮罩相关DOM元素 const uploadMask = document.getElementById('upload-mask'); const progressBar = document.getElementById('progress-bar'); const progressText = document.getElementById('progress-text'); const uploadToFirebase = e => { e.preventDefault(); if (!image) { alert("Please upload an image first."); return; } // 初始化上传状态:显示遮罩、重置进度 uploadMask.style.display = 'flex'; progressBar.style.width = '0%'; progressText.textContent = '上传中 0%'; // 监听页面关闭/跳转事件 const preventLeave = (e) => { e.preventDefault(); e.returnValue = '文件正在上传,确定离开当前页面吗?'; return e.returnValue; }; window.addEventListener('beforeunload', preventLeave); const storageRef = storage.ref(`${user1}/${tripid}/documents`); const imageRef = storageRef.child(image.name); const uploadTask = imageRef.put(image); uploadTask.on('state_changed', // 进度更新回调 (snapshot) => { const percent = Math.round((snapshot.bytesTransferred / snapshot.totalBytes) * 100); progressBar.style.width = `${percent}%`; progressText.textContent = `上传中 ${percent}%`; }, // 上传失败回调 (err) => { window.removeEventListener('beforeunload', preventLeave); uploadMask.style.display = 'none'; alert(`上传失败:${err.message}`); }, // 上传完成回调 () => { window.removeEventListener('beforeunload', preventLeave); uploadMask.style.display = 'none'; alert("Successfully uploaded."); getFromFirebase(); } ); };
注意事项
- 无论上传成功还是失败,一定要移除
beforeunload事件监听、隐藏遮罩层,避免上传结束后用户仍无法正常操作页面 - 如果项目用的是React/Vue等框架,把DOM操作换成框架对应的状态绑定即可,核心逻辑不变
- 遮罩层不要加关闭按钮,强制用户等待上传完成
内容的提问来源于stack exchange,提问作者Paul VI
相关产品推荐
相关产品推荐

