Vue+el-upload上传文件,覆盖默认的上传行为,可以自定义上传的实现

<template>
  <div>
    <el-upload class="upload-demo" action size="mini" :file-list="fileListone" :http-request="uploadMehod">
      <el-button size="mini" type="primary" :loading="loadingOne">上传</el-button>
      <div slot="tip" class="el-upload__tip">注:单文件上传</div>
    </el-upload>
  </div>
</template>

<script>
export default {
  data: function() {
    return {
      loadingOne: false,
      fileListone: [],
    }
  },
  methods: {
    async uploadMehod(params) {
      this.loadingOne = true
      this.fileListone.unshift(params.file)
      let formData = new FormData()
      formData.append('file', params.file)
      let { data } = await setDelivery(formData) //axios
      if (data === 'success') {
        this.$message.success(data)
      } else {
        this.$message.error(data)
      }
      this.loadingOne = false
    },
  }
}
</script>
<style scoped lang="scss">
::v-deep input {
  width: 200px;
}
.el-upload__tip {
  color: red;
}
</style>
<think>我们正在处理一个关于Vue2中el-upload组件的问题。用户想要知道如何自定义上传方法,并在上传成功后获取文件列表。 根据引用内容,我们有一个Vue3的例子,但用户需要的是Vue2的解决方案。不过,el-uploadVue2和Vue3中的用法类似,我们可以借鉴。 关键点: 1. 自定义上传方法:使用`:http-request`属性覆盖默认上传行为。 2. 上传成功后获取文件列表:我们需要在自定义上传方法中手动触发文件列表的更新,因为自定义上传方法不会自动更新文件列表。 步骤: 1.el-upload组件中设置`:auto-upload="false"`(如果需要手动触发上传)以及`:http-request="httpRequest"`(指定自定义上传方法)。 2.自定义上传方法中,我们执行实际的上传请求(如使用axios),并在上传成功后调用`onSuccess`回调(这个回调由el-upload传入)来通知上传成功,同时更新文件列表。 3. 我们可能还需要在文件选择后手动控制文件列表,以便在界面上正确显示。 注意:在自定义上传方法中,我们需要手动更新文件列表(通过el-upload的ref调用clearFiles等方法,或者通过维护一个本地的文件列表状态)。 然而,用户提到“上传成功后获取文件列表”,有两种理解: a. 获取当前已经上传文件列表(即el-upload组件内部维护的fileList) b. 获取服务器返回的上传成功后的文件信息列表 根据问题,应该是a,即获取组件内部的文件列表。但通常,我们还需要将服务器返回的文件信息(如url)添加到文件列表中。 因此,我们通常这样做: -自定义上传方法中,当上传成功时,调用`onSuccess`回调,并传入服务器的响应,这样el-upload会自动将当前上传文件状态改为成功,并更新文件列表。 - 同时,我们也可以使用ref来访问el-upload组件的fileList。 但是,如果我们使用了自定义上传方法(覆盖默认上传),那么el-upload不会自动更新文件列表,所以我们需要在自定义上传方法中手动更新。我们可以通过两种方式: 1. 使用ref访问组件的方法,比如`this.$refs.upload.clearFiles()`清除文件列表,或者通过修改fileList属性(需要.sync修饰符)来更新。 2.自定义上传方法中,我们调用el-upload传入的`onSuccess`回调,这样el-upload就会自动更新该文件的状态为成功。 实际上,在自定义上传方法中,el-upload会传入一个对象,包含: - file: 当前上传文件 - onProgress: 更新上传进度的回调 - onSuccess: 上传成功的回调 - onError: 上传失败的回调 - ...等 因此,我们在自定义上传方法中,只要在请求成功后调用onSuccess,el-upload就会更新该文件的状态。 同时,我们也可以使用ref获取文件列表:`this.$refs.upload.uploadFiles`(注意,ref为uploadRef,则用`this.$refs.uploadRef.uploadFiles`) 所以,具体步骤: 1. 在组件中定义el-upload,并设置`auto-upload`为false(如果选择文件后自动上传则不需要,但这里我们通常手动控制)和指定`http-request`: ```html <el-upload ref="uploadRef" action="#" <!-- 因为自定义上传,所以action可以写个占位符 --> :auto-upload="false" :http-request="httpRequest" :multiple="false" :limit="1" accept=".gltf,.glb" :file-list="fileList" <!-- 绑定一个本地的fileList,这样我们可以控制 --> > <el-button slot="trigger" size="small" type="primary">选取文件</el-button> <el-button style="margin-left: 10px;" size="small" type="success" @click="submitUpload">上传到服务器</el-button> <div class="el-upload__tip">gltf/glb文件,限制数量1</div> </el-upload> ``` 2. 在data中定义fileList数组: ```javascript data() { return { fileList: [] // 用于显示的文件列表 }; } ``` 3. 定义httpRequest方法(自定义上传方法): ```javascript methods: { httpRequest(options) { // options是一个对象,包含file, onProgress, onSuccess, onError等 const formData = new FormData(); formData.append(options.filename, options.file); // 使用axios或者其他方法上传 axios.post(options.action, formData, { onUploadProgress: (progressEvent) => { // 调用onProgress更新进度 const percent = (progressEvent.loaded / progressEvent.total) * 100; options.onProgress({ percent }); } }).then(res => { // 上传成功,调用onSuccess,参数为响应数据(根据需要传入,可以传入服务器返回的文件信息) options.onSuccess(res.data); // 注意:调用onSuccess后,el-upload会自动将文件状态改为成功,并更新其内部的fileList,但是我们绑定了fileList,所以需要通过绑定的fileList来更新?实际上,如果我们绑定了:file-list并且使用.sync,那么我们需要自己维护。否则,el-upload内部会维护,我们可以通过ref获取。 // 如果我们绑定了:file-list="fileList",那么el-upload不会自动更新我们本地的fileList,所以我们需要手动更新。因此,这里我们选择不绑定fileList到el-upload,而是通过ref来获取内部状态?或者我们也可以自己维护。 // 两种方式: // 方式一:不绑定file-list,那么el-upload内部维护,我们可以通过ref获取(this.$refs.uploadRef.uploadFiles) // 方式二:绑定file-list并且使用.sync,然后手动更新(推荐) // 这里我们采用方式一,因为简单,而且用户只需要获取上传后的文件列表。 }).catch(err => { options.onError(); }); }, submitUpload() { // 手动触发上传 this.$refs.uploadRef.submit(); } } ``` 4. 如何获取文件列表?在上传成功后,我们可以通过`this.$refs.uploadRef.uploadFiles`来获取文件列表。 但是,注意:我们调用onSuccess后,el-upload会更新该文件的状态,所以uploadFiles也会更新。 如果我们想要在别的时机获取,比如在提交表单时,我们就可以通过这个ref获取。 然而,如果我们希望每次上传成功都做一些事情,可以在调用onSuccess后紧接着获取文件列表。 但是,如果我们绑定了file-list,那么我们可以直接使用我们自己的fileList变量。所以,我们可以修改为: ```html <el-upload ... :file-list="fileList" ... > ``` 然后在httpRequest中,我们不需要自己修改fileList,但是调用onSuccess后,el-upload会更新fileList吗?实际上,如果我们绑定了file-list,那么el-upload会触发update:file-list事件,所以我们需要使用.sync修饰符来同步。 Vue2中,我们可以这样: ```html :file-list.sync="fileList" ``` 这样,el-upload内部更新fileList时会更新我们的fileList变量。 或者,我们也可以不使用.sync,而是监听change事件来更新fileList。 但是,更简单的方式是不绑定file-list,然后通过ref获取。 根据element-ui的文档,自定义上传方法后,且不绑定file-list,那么el-upload内部会维护一个fileList(通过ref可以访问到)。所以我们不需要在data中声明fileList,然后通过ref访问。 因此,我们可以这样: ```html <el-upload ref="uploadRef" action="#" :auto-upload="false" :http-request="httpRequest" :multiple="false" :limit="1" accept=".gltf,.glb" > ...按钮等 </el-upload> ``` 然后,在httpRequest中,我们调用onSuccess后,文件列表会自动更新(在el-upload内部)。我们可以这样获取文件列表: ```javascript this.fileList = this.$refs.uploadRef.uploadFiles; // 注意,这是一个计算属性?实际上,它是一个数组,但是它是组件内部的状态,所以我们可以直接访问。 // 但是,如果我们想在其他地方获取,比如在提交表单时,我们可以直接访问这个ref的uploadFiles。 ``` 另外,如果我们想要在文件选择后手动控制,可以使用`on-change`事件。但是,这里我们使用自定义上传,所以文件选择后并不会自动上传。 总结:自定义上传方法,并在上传成功后调用onSuccess,然后通过ref获取文件列表。 参考代码: ```vue <template> <div> <el-upload ref="uploadRef" action="#" :auto-upload="false" :http-request="httpRequest" :limit="1" accept=".gltf,.glb" > <el-button slot="trigger" type="primary">选择文件</el-button> <el-button type="success" @click="submitUpload">上传</el-button> </el-upload> <el-button @click="getFileList">获取文件列表</el-button> </div> </template> <script> export default { methods: { // 自定义上传方法 httpRequest(options) { // 模拟上传 console.log(options.file); // 模拟一个上传进度 let progress = 0; const timer = setInterval(() => { progress += 20; options.onProgress({ percent: progress }); if (progress >= 100) { clearInterval(timer); // 假设上传成功 options.onSuccess({ data: { url: 'http://example.com/file.gltf' } }); } }, 200); }, submitUpload() { this.$refs.uploadRef.submit(); }, getFileList() { console.log(this.$refs.uploadRef.uploadFiles); } } } </script> ``` 注意:在实际项目中,我们可能需要使用axios等库上传,并在真实的请求完成后调用onSuccess。 另外,如果我们需要在文件上传成功后执行其他操作(比如获取服务器返回的url并保存),可以在调用onSuccess之前或之后处理。但是,注意onSuccess调用后,el-upload会更新文件的状态(变为success),所以我们可以将服务器返回的数据传递给onSuccess,这样el-upload会将该文件的状态设置为成功,并保存response(我们可以从文件对象的response属性获取)。 因此,在模板中,我们也可以显示上传成功的文件信息: ```html <div v-for="file in $refs.uploadRef?$refs.uploadRef.uploadFiles:[]" :key="file.uid"> {{ file.name }} - {{ file.status }} <span v-if="file.status==='success'">({{ file.response.data.url }})</span> </div> ``` 但是,注意在模板中直接使用ref可能不是响应式的,因为ref的更新不会触发模板重新渲染(除非在模板中引用的响应式数据变化)。所以,更好的做法是使用绑定的fileList(使用.sync或者自己维护)。 所以,如果我们希望响应式地显示文件列表,我们可以: 1. 使用:file-list.sync="fileList",然后在httpRequest中不需要手动更新,因为el-upload会同步更新fileList。 2. 在httpRequest中调用onSuccess后,我们可以更新本地的fileList,但是这样重复。 这里,我们推荐使用.sync的方式: ```html <el-upload :file-list.sync="fileList" ...其他属性 > ``` 然后在data中定义fileList: [] 这样,在httpRequest中调用onSuccess后,fileList会自动更新(因为el-upload内部会触发update:fileList事件)。 因此,我们可以这样写: ```vue <template> <div> <el-upload ref="uploadRef" action="#" :auto-upload="false" :http-request="httpRequest" :limit="1" accept=".gltf,.glb" :file-list.sync="fileList" > <el-button slot="trigger" type="primary">选择文件</el-button> <el-button type="success" @click="submitUpload">上传</el-button> </el-upload> <div> 文件列表: <div v-for="(file, index) in fileList" :key="index"> {{ file.name }} - {{ file.status }} </div> </div> <el-button @click="getFileList">获取文件列表</el-button> </div> </template> <script> export default { data() { return { fileList: [] }; }, methods: { httpRequest(options) { // 模拟上传 const formData = new FormData(); formData.append('file', options.file); // 使用axios上传 axios.post('your_upload_url', formData, { onUploadProgress: (progressEvent) => { const percent = (progressEvent.loaded / progressEvent.total) * 100; options.onProgress({ percent: percent }); } }).then(res => { // 上传成功,调用onSuccess,并传入响应数据,注意响应数据会被放入file.response中 options.onSuccess(res); // 这里不需要单独更新fileList,因为.sync会同步 }).catch(err => { options.onError(err); }); }, submitUpload() { this.$refs.uploadRef.submit(); }, getFileList() { console.log(this.fileList); } } } </script> ``` 注意:在httpRequest中,我们调用onSuccess时,传入的是整个响应对象(res),这样在file.response中就会是res。如果我们只需要res的一部分,可以传入res.data。 因此,根据用户需求,我们提供了自定义上传方法,并在上传成功后可获取文件列表(通过绑定的fileList或ref获取)。 用户可以根据需要选择方式。 最后,用户的问题是在Vue2中,我们使用的是element-ui(对应Vue2),而引用中给出的是Vue3(对应element-plus),但是api基本一致。 请用户根据实际情况调整。 </think>在 Vue2 中使用 Element UI 的 `el-upload` 组件实现自定义上传并获取文件列表的方法如下: ### 核心步骤说明 1. **自定义上传方法**:使用 `http-request` 属性覆盖默认上传逻辑 2. **手动触发上传**:设置 `auto-upload="false"` 并通过按钮手动提交 3. **获取文件列表**:通过 `ref` 访问上传组件实例获取文件列表 4. **响应上传结果**:在自定义上传逻辑中处理成功/失败回调 ### 代码实现 ```vue <template> <div> <!-- 自定义上传组件 --> <el-upload ref="myUpload" <!-- 注册引用 --> action="#" <!-- 占位符(必须存在) --> :auto-upload="false" <!-- 关闭自动上传 --> :http-request="customUpload" <!-- 自定义上传逻辑 --> :show-file-list="true" <!-- 显示文件列表 --> :multiple="false" <!--文件上传 --> :limit="1" <!-- 限制1个文件 --> > <el-button slot="trigger">选择文件</el-button> <el-button type="success" @click="submitUpload">确认上传</el-button> </el-upload> <!-- 显示获取的文件列表数据 --> <div v-if="fileList.length > 0"> <h3>已上传文件列表:</h3> <ul> <li v-for="(file, index) in fileList" :key="index"> {{ file.name }} (状态: {{ file.status }}) </li> </ul> </div> </div> </template> <script> export default { data() { return { fileList: [] // 存储获取的文件列表 }; }, methods: { // 自定义上传方法(核心) customUpload(options) { const { file, onSuccess, onError } = options; // 1. 构造FormData const formData = new FormData(); formData.append('file', file); // 字段名根据后端要求调整 // 2. 发起实际请求(示例使用axios) this.$axios.post('/your/upload/api', formData, { headers: { 'Content-Type': 'multipart/form-data' } }).then(response => { // 3. 触发成功回调(更新组件内部状态) onSuccess(response.data); // 4. 获取更新后的文件列表(通过ref) this.getFileList(); }).catch(error => { // 错误处理 onError(error); }); }, // 手动提交上传 submitUpload() { this.$refs.myUpload.submit(); }, // 获取文件列表方法 getFileList() { // 访问组件实例的uploadFiles属性 this.fileList = this.$refs.myUpload.uploadFiles; // 可选的调试输出 console.log('当前文件列表:', this.fileList); } } }; </script> ``` ### 关键点解析 1. **`http-request` 自定义上传** - 覆盖默认上传逻辑,参数 `options` 包含: - `file`: 当前上传文件对象 - `onSuccess()`: 必须调用的成功回调函数 - `onProgress()`: 更新进度条的回调 - `onError()`: 错误处理回调 2. **文件列表获取** 通过组件实例的 `uploadFiles` 属性获取,包含所有文件对象的数组,每个文件对象包含: ```js { uid: '唯一ID', // 文件唯一标识 name: '文件.jpg', // 文件名 size: 1024, // 文件大小(字节) status: 'success', // 状态(ready/uploading/success/fail) percentage: 100 // 上传进度百分比 } ``` 3. **手动触发上传流程** - 用户选择文件 → 点击"确认上传"按钮 → 触发 `submit()` 方法 - 每个文件会单独调用 `http-request` 定义的方法 ### 注意事项 1. **`action` 属性** 即使使用自定义上传仍需保留 `action="#"` 属性占位,否则组件会报错 2. **文件状态同步** 在自定义上传中必须调用 `onSuccess()` / `onError()`,否则组件无法更新文件状态 3. **清空文件列表** 可通过 `this.$refs.myUpload.clearFiles()` 重置文件列表 4. **多文件处理** 使用 `multiple` 时,`customUpload` 会对每个文件单独调用 --- ### 相关问题 1. 如何在文件上传时显示实时进度条? 2. 上传前如何校验文件类型和大小? 3. Vue2 和 Vue3 的 el-upload 使用有哪些主要区别? 4. 如何实现拖拽文件上传功能? 5. 文件上传失败后如何实现自动重试? [^1]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值