Element Plus Upload 添加支持拖拽排序~

本文首发于公众号:执行上下文,同步更新个人博客:坚果大叔,转载请署名。更多知识点不断更新中!!

前提

项目中使用element-plus ui框架作为基础项目组件,使用了其中的upload上传组件,在后续过程中提出需求需要支持拖拽排序,我...

但是原有的 upload 组件在其他方面都支持的很好,唯独没有没有支持拖拽这个功能,没有办法只能自己二次加工了。

组件的结构

组件主要分为三个部分:

  1. 上传 : 使用原有的upload 组件
  2. 拖拽 : 使用第三方插件 draggable 来实现图片列表的拖拽效果
  3. 预览: 因为没有使用原生组件,所以自带的预览也就没有了。

拖拽功能的思路

1. 使用draggable并设置相应的参数

vue 复制代码
<draggable
  v-model="fileList"
  item-key="uid"
  class="draggable-list"
  :animation="200"
  ghost-class="ghost"
  @end="onDragEnd"
>

关键配置:

  • item-key="uid": 指定每个拖拽项的唯一标识符
  • :animation="200": 设置拖拽动画时长为200ms
  • ghost-class="ghost": 拖拽时的幽灵元素样式类
  • @end="onDragEnd": 拖拽结束时的回调函数

2. 拖拽template的整体结构

vue 复制代码
<template #item="{ element: file }">
  <div class="draggable-item">
    <img
      class="el-upload-list__item-thumbnail"
      :src="file.url"
      alt=""
    />
    <!-- 状态显示层 -->
    <div v-if="file.status === 'uploading'" class="upload-progress">
      <el-progress
        type="circle"
        :percentage="file.percentage || 0"
        :width="60"
      />
    </div>
    <!-- 操作按钮层 -->
    <span class="el-upload-list__item-actions">
      <!-- 预览和删除按钮 -->
    </span>
  </div>
</template>

3. 拖拽事件处理

因为是使用的成熟的第三方库,所以我们不需要关系拖拽的底层逻辑,只需要在应用层做相关的处理。

typescript 复制代码
// 拖拽结束处理函数
const onDragEnd = () => {
  emit("update:modelValue", fileList.value);
};

一些注意点

1. 数据的实时更新

typescript 复制代码
const fileList = ref<UploadUserFile[]>(props.initFiles);

// 监听文件列表变化,同步到父组件
watch(fileList, (newVal) => {
  emit("update:modelValue", newVal);
});

2. 删除已上传的文件并且更新

typescript 复制代码
const handleRemove = (
  uploadFile: UploadUserFile,
  uploadFiles?: UploadUserFile[]
) => {
  if (uploadFiles) {
    fileList.value = uploadFiles;
  } else {
    // 从拖拽列表中删除
    const index = fileList.value.findIndex(
      (file) => file.uid === uploadFile.uid
    );
    if (index > -1) {
      fileList.value.splice(index, 1);
      emit('update:modelValue', fileList.value);
    }
  }
};

3. 添加上传进度展示

typescript 复制代码
// 上传进度回调
(percent) => {
  const fileIndex = fileList.value.findIndex(
    (f) => f.uid === file.uid
  );
  if (fileIndex !== -1) {
    fileList.value[fileIndex] = {
      ...fileList.value[fileIndex],
      percentage: percent,
    };
  }
}

设计亮点:

  • 实时更新上传进度
  • 通过 uid 精确定位文件
  • 使用展开运算符保持对象不可变性

CSS 拖拽状态样式

scss 复制代码
// 添加幽灵效果
.ghost {
  opacity: 0.5;
  transform: scale(0.95);
}

总结和效果

既然原有组件不支持相关业务功能,我们不必执着于去改造他,换个思路,可以只保留他的核心上传的功能,其他像拖拽、预览、上传进度可以通过自定义的方式来实现。

毕竟没有哪个第三方组件能完美适配每一个项目,该造的轮子还是要造的。

相关推荐
2601_949868366 分钟前
Flutter for OpenHarmony 剧本杀组队App实战04:发起组队表单实现
开发语言·javascript·flutter
小白640217 分钟前
2025年终总结-迷途漫漫,终有一归
前端·程序人生
烟花落o21 分钟前
贪吃蛇及相关知识点讲解
c语言·前端·游戏开发·贪吃蛇·编程学习
kgduu22 分钟前
js之javascript API
javascript
晚霞的不甘25 分钟前
Flutter for OpenHarmony专注与习惯的完美融合: 打造你的高效生活助手
前端·数据库·经验分享·flutter·前端框架·生活
kogorou0105-bit36 分钟前
前端设计模式:发布订阅与依赖倒置的解耦之道
前端·设计模式·面试·状态模式
止观止1 小时前
像三元表达式一样写类型?深入理解 TS 条件类型与 `infer` 推断
前端·typescript
xiaoqi9221 小时前
React Native鸿蒙跨平台实现图片画廊类页面是视觉展示型APP(如摄影类、图库类、设计类APP)的核心载体,其核心需求是实现图片的流畅渲染
javascript·react native·react.js·ecmascript·harmonyos
雪芽蓝域zzs1 小时前
uniapp 省市区三级联动
前端·javascript·uni-app
Highcharts.js1 小时前
Next.js 集成 Highcharts 官网文档说明(2025 新版)
开发语言·前端·javascript·react.js·开发文档·next.js·highcharts