用 reactive 管理多文件上传状态更优,因其可直接响应式修改对象属性,避免频繁 .value 操作;需为每个文件封装 id、file、status 等字段,并就地更新 status/progress/message 等属性以保持响应性。

用 reactive 管理多文件上传列表的成功与失败状态,关键在于把每个文件的元信息和状态封装成响应式对象,并统一维护在 reactive 对象中。它比 ref 更适合管理结构较复杂的列表(如含 status、progress、name、id 等字段的文件集合),避免频繁 .value 操作,语义更清晰。
✅ 用 reactive 定义上传文件列表
import { reactive } from 'vue'
const uploadState = reactive({
fileList: [], // 存储所有待传/已传/失败的文件项
uploading: false,
})
每个文件项建议包含这些字段:
-
id: 唯一标识(推荐用Date.now() + Math.random()生成) -
file: 原始 File 对象(仅用于上传,不需响应式) -
name,size,type: 可直接提取展示 -
status:'idle' | 'uploading' | 'success' | 'error' -
progress:0–100数字(可选) -
message: 错误提示或成功描述(可选)
示例初始化:
const addFiles = (files) => {
const newItems = Array.from(files).map(file => ({
id: Date.now() + Math.random().toString(36).substring(2, 9),
file,
name: file.name,
size: file.size,
type: file.type,
status: 'idle',
progress: 0,
message: '',
}))
uploadState.fileList.push(...newItems)
}
✅ 状态更新要“就地修改”,保持响应式
reactive 包裹的对象,直接修改属性即可触发更新(不需要 push/splice 重赋值整个数组):
// 开始上传某文件
const startUpload = (id) => {
const item = uploadState.fileList.find(f => f.id === id)
if (item) {
item.status = 'uploading'
item.progress = 0
}
}
// 上传成功
const markSuccess = (id, serverData) => {
const item = uploadState.fileList.find(f => f.id === id)
if (item) {
item.status = 'success'
item.message = '上传完成'
item.url = serverData.url // 可存服务器返回路径
}
}
// 上传失败
const markError = (id, errorMsg) => {
const item = uploadState.fileList.find(f => f.id === id)
if (item) {
item.status = 'error'
item.message = errorMsg || '上传失败,请重试'
}
}
⚠️ 注意:不要写 item = {...item, status: 'success'} —— 这会丢失响应性;必须原对象赋值。
使用 `@ainative/vue-sdk` 为 Vue 3 应用添加 AI 聊天功能。适用于以下场景:(1) 安装 `@ainative/vue-sdk`,(2) 在 Vue 组件中使用 `useChat` 组合式函数,(3) 提供……
✅ 模板中按状态区分渲染(简洁直观)
<div v-for="file in uploadState.fileList" :key="file.id">
<span>{{ file.name }}</span>
<span v-if="file.status === 'idle'">等待上传</span>
<span v-else-if="file.status === 'uploading'">
上传中 {{ file.progress }}%
</span>
<span v-else-if="file.status === 'success'" style="color: green">
✓ 已成功
</span>
<span v-else-if="file.status === 'error'" style="color: red">
✗ {{ file.message }}
</span>
</div>
也可配合 Element Plus 的 el-tag 或自定义图标增强体验。
✅ 批量上传时的状态协同控制
若需“全量上传”按钮,可加一个 uploadAll 方法:
const uploadAll = async () => {
uploadState.uploading = true
try {
for (const item of uploadState.fileList) {
if (item.status === 'idle') {
await uploadSingleFile(item)
}
}
} finally {
uploadState.uploading = false
}
}
其中 uploadSingleFile(item) 内部调用 startUpload → markSuccess / markError,形成闭环。
不复杂但容易忽略
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!









