技术栈:

Vue3+ts+vant

背景:

最近移动端项目中遇到了一个比较有意思的问题,需要根据不同的类别来上传对应的图片,并且将图片转换为url地址,在提交结果时,将地址也一并带上,最后一起上传。

具体需求的样图如下:

 点击加减号添加项目名称,

 选择完后弹框弹出对应名称,并且需要上传图片

个人遇到的问题:

上传图片本身不是什么难事,毕竟vant组件库已经是一个相对完善的组件库了,但是问题在于,如果未点击提交时关闭了弹框,此时又在加减号时添加了别的名称,再次弹框,按照原本组件库的逻辑就会出现图片无法对应名称的情况,并且点击x,想要删除图片时,就会报错
 

分析原因:

由于默认的uploader绑定的是一个数组,当我们改变了名称并再次弹框时,数组长度发生了变化,但是没有对应其名称,因此造成了错位的情况,在原数组中找不到对应名称的数组,在删除时就会出现问题

解决办法:

因为数组没办法做到图片和名称项对应,所以我们不考虑使用数组,改用对象的方式来存储图片

并且将上传和删除的回调函数写成如下模式

        <Field
          v-for="(item, index) in state.category.filter((target) => {
              return target.submitResult > 0;
          })"
          :key="item.defectCategoryCode"
          name="'uploader-' + index"
          :label="item.defectProjectName"
        >
          <template #input>
            <Uploader
              multiple 
              :max-count="3"
              capture="camera"
              :key="'uploader-' + index"
              preview-size="76"
              v-model="fileList[item.code]" // 这个绑定对象,并用唯一的item.code做属性名
              :before-read="beforeRead" // 上传前先压缩,这个可以自己写一下
              :after-read="(file) => afterRead(file, item)" // 上传后转换为url
              :before-delete="
                (file, detail) => beforeDelete(file, item, item.code, detail) // 删除图片
              "
            />
          </template>
        </Field>

上传时将原本绑定的数组改为对象,存储时以键值对的形式去存,属性名为唯一的code,值为对应的数组,在afterRead中,将每一项数据带入作为参数,并且将得到的url拼接到对应项的images中。

删除时将需要删除的fileList,每一项,每一项的code,以及index都传入,在fileList删除对应的上传图片,在item.images中删除对应url

const fileList = ref({}); // 图片数组
// 上传图片
const afterRead = async (file: any, item: any) => {
  const formData = new FormData();
  formData.append('file', file.file);
  const res = await uploadImage(formData); // 图片上传
  const regex = /^(.*?)(?=\?)/;
  const url = res.data.match(regex)[1];
  if (res.success) {
    item.images = item.images
      ? (item.images += `,${url}`)
      : (item.images = url);
  }
};

// 删除图片
const beforeDelete = (file: any, item: any, name: any, detail: any) => {
  const urlList = item.images.split(',');
  urlList.splice(detail.index, 1);
  (fileList.value as any)[name].splice(detail.index, 1);
  item.images = urlList.join(',');
};

同时需要在弹框被关闭的colse方法中,将关闭时的图片信息都存进去,当再次打开弹框时,对比已经存储的信息和最新收集的信息是否相同,若相同则不做处理,不相同则替换掉,之后再打开弹框。 

const closeHandle = () => {
  modifyFlag.value = true;
  temInfo.value = state.category;
};

const index = temInfo.value.findIndex(
          (categoryItem: any) => categoryItem.code === item.code
        );
        if (index !== -1) {
          temInfo.value[index].submitResult = item.submitResult;
        } else {
          temInfo.value.push(item);
        }
      });
      state.category = modifyFlag.value ? temInfo.value : await getTargetInfo();
// getTargetInfo()为收集最新数据的函数
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

这样的话即使弹框被关闭或者修改选项,也能保证图片的上传和删除不受影响,并且不会报错,这个问题本身不算是什么大问题,就是对组件库的熟悉度不够导致的,在日后的开发中还需要深入对组件库的各种组件的理解和研究。

Logo

前往低代码交流专区

更多推荐