Antd Upload图片墙拖拽改造

最近产品提了个需求,就是希望图片墙的图片能拖拽来改变图片顺序。
本坑使用的antd的Upload组件,本身是没有拖拽的。要新加个插件吗?时间来不及了吧?
于是乎看看能不能在目前组件上改造它?
原本:


原本

改造后的效果,gif放的有点慢,实际没有这么慢

改造后

        <Upload
          action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
          listType="picture-card"//图片墙样式
          fileList={fileList}
          onPreview={this.handlePreview}
          onChange={this.handleChange}
        >
          {fileList.length >= 8 ? null : uploadButton}
        </Upload>

分两步
1、upload 当鼠标在图片上时有个遮罩,这阻挡了拖拽功能的顺畅进行,需要把遮罩放到顶部或者是底部。
2、添加拖拽的监听,这个部分有些细节要注意

样式的改造:当鼠标放到顶部时,把操作放在顶部

//这种全局的样式设置 className={styles.id}来这设置它的class
# id{
  :global {
    .ant-upload-list-picture-card .ant-upload-list-item-info::before {
      height: 20px;
    }
    .ant-upload-list-picture-card .ant-upload-list-item-actions {
      top: 8px;
      transform: translate(-50%, 0);
    }
  }
}
使用useEffect来添加和去除监听
有两个细节问题:
i:删除和新增图片操作会触发getFieldValue("fileList")变更时,实际图片列表dom没有立即同步的,所以如果以前者为依据![未命名1.gif](https://upload-images.jianshu.io/upload_images/4455053-8c07d42905e2b16e.gif?imageMogr2/auto-orient/strip)
来实现拖拽后的逻辑就会有出入。
删除操作时:dom上的class 的变更是和getFieldValue("fileList")同步的。可以通过class来计算出那些图片成员是正在删除的。
新增时:dom的新增会快于getFieldValue("fileList")的新增。
ii:拖拽的api要实现顺利的拖拽 draggerover必须要e.preventDefault() ondrop才能顺利获得setData的内容


  useEffect(() => {
    //收集图片dom
    let images = document.querySelectorAll('#picWall .ant-upload-list-item-image');
 
    if (images && images.length > 0) {
      //收集图片dom所在的item dom 准备查看item是否有remove className
      let items = document.querySelectorAll('#picWall .ant-upload-list-item');
      let removeIndex = [].findIndex.call(
        items,
        el =>
          // ant-upload-list-item-removed  ant-upload-animate-inline-leave  -----正在操作去除的class
          [...el.classList].includes('ant-upload-list-item-removed') ||
          [...el.classList].includes('ant-upload-animate-inline-leave'),
      );
      //如果image所在的item有remove class 则必须过滤掉
      let els = [].filter.call(images, (el, index) => index !== removeIndex);
      [].forEach.call(els, (el, index) => {
每次触发重新设置key
        el.setAttribute('key', index);
        //如果已经设置draggable说明已经添加事件监听,无需再添加监听
        if (!el.attributes.draggable) {
          el.setAttribute('draggable', true);
          el.addEventListener('dragstart', e => {
            e.dataTransfer.setData('key', Number(e.target.attributes.key.value));
          });
          el.addEventListener('dragenter', e => {});
          el.addEventListener('dragover', e => e.preventDefault());
          el.addEventListener('drop', e => {
            e.preventDefault();
            e.stopPropagation();
            const oldIndex = e.dataTransfer.getData('key');
            const newIndex = e.target.attributes.key.value;
            if (oldIndex != newIndex) {
              console.log(oldIndex, newIndex, getFieldValue('files'));
              let fileList = JSON.parse(JSON.stringify(getFieldValue('files')));
//拖拽后的逻辑
              if (newIndex > oldIndex) {
                var temp = fileList[oldIndex].url || fileList[oldIndex].response.data;
                for (var i = Number(oldIndex); i < Number(newIndex); i++) {
                  fileList[i].url = fileList[i + 1].url || fileList[i + 1].response.data;
                }
                fileList[newIndex].url = temp;
              } else {
                var temp = fileList[oldIndex].url || fileList[oldIndex].response.data;
                for (var i = Number(oldIndex); i > Number(newIndex); i--) {
                  fileList[i].url = fileList[i - 1].url || fileList[i - 1].response.data;
                }
                fileList[newIndex].url = temp;
              }
              fileList.forEach(i => {
                if (i.url) {
                  delete i.thumbUrl;
                  delete i.response;
                }
              });
              setFiles(fileList);
              setFieldsValue({ files: fileList });
            }
          });
        }
      });
    }

    return () => {
      let els = document.querySelectorAll('#picWall .ant-upload-list-item-image');
      [].forEach.call(els, el => {
        el.removeEventListener('dragstart', () => {});
        el.removeEventListener('drop', () => {});
        el.removeEventListener('dragenter', e => {});
        el.removeEventListener('drageover', e => {});
      });
    };
  }, [
    getFieldValue('files'),
    //当上传图片后getFieldValue('files')发生变化,但是还没有异步获取上传图片路径时,此时document.querySelectorAll('#picWall .ant-upload-list-item-image')没有变化
    //通过监听图片dom长度再次触发useEffect,监听新增的图片dom
    document.querySelectorAll('#picWall .ant-upload-list-item-done').length,
  ]);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容