关于javascript:封装一个支付宝小程序的upload文件上传组件☀☀☀

一、序言

上传图片以及大图预览应该是小程序中比拟罕用的api了,

然而很惋惜,官网的mini-ali-ui并没有提供相干的ui组件

(微信罕用的Vant-Weapp就提供了uploader文件上传组件,😵)

(不晓得啥起因,2022年3月21日开始,mini-ali-ui将不再更新或降级,6月22日将下线相干文档⏰)

没方法,官网不提供,然而本人开发中又常常用到,所以咱们本人来疾速封装一个繁难的upload组件吧

支付宝小程序自定义组件的相干内容请参考官网文档:https://opendocs.alipay.com/m…

二、筹备工作

次要的筹备工作就两个

下载这两个图片!

😤😤😤


三、实现

简略梳理一下需要:

⭐默认展现一个‘+’,点击的时候,能够让用户抉择照片或者拍照

⭐须要一个图片url数组,按程序展现数组中的图片,如果图片的数量小于最大上传数量,则在最初面显示‘+’号让用户持续上传

⭐图片右上角显示删除图标,点击之后返回图片在数组中的索引,在父组件自定义删除逻辑

⭐点击图片可大图预览

⭐上传胜利之后返回图片的长期门路(本地门路),在父组件自定义本人的业务上传逻辑

PS:图片数组是由父组件传入的,不肯定传入空数组,也能够传入曾经存在图片url的数组。
  😏因而这个组件只有稍加革新,加一个参数emmm,就能变成一个缩略图预览组件。

PPS:(在理论利用中,小程序上的数据可能来源于一些pc平台的文件上传,这就可能导致后盾返回的文件数组中存在一些pdf、word等其余格局的文件,支付宝小程序反对pdf文件查看,所以这里能够再优化一下✅)

话不多说,上代码


🅰upload.axml

<view class='view-row'>
  <!-- 如果图片的url为空 -->
  <block a:if="{{fileList.length === 0 && !onlyShow}}">
    <view class='upload' onTap='upFile'>
      <image class='view-half-full' src="/images/ic_pic_add.png" />
    </view>
  </block>
  
  <!-- 图片的url不为空 -->
  <block a:else>
    <!-- 首先按程序渲染图片 -->
    <view class='flex-wrap'>
      <view class='upload' a:for="{{fileList}}" a:key="{{index}}">
        <image class='view-full' src="{{item}}" data-index="{{index}}" onTap='preViewImage' />
        <image a:if='{{!onlyShow}}' class='delete' src="/images/ic_pic_delete.png" data-index="{{index}}" onTap='deleteImage' />
      </view>
      
      <!-- 渲染上传图标 -->
      <view a:if='{{fileList.length < maxLength && !onlyShow}}' class='upload' onTap='upFile'>
        <image class='view-half-full' src="/images/ic_pic_add.png" />
      </view>
    </view>
  </block>
</view>

🅱upload.js

Component({
  mixins: [],
  data: {},
  props: {
    name: null,
    fileList: [], //显示的图片的url
    maxLength: 5, //上传图片的个数 默认为5
    onlyShow: false,// 是否仅仅展现图片,不显示上传及删除按钮
    sourceType: ['camera', 'album'],
    onActive: (res,name) => {
      console.log(res,name)
    },
    onDelete: (index,name) => {
      console.log(index,name)
    }
  },
  didMount() { },
  didUpdate() { },
  didUnmount() { },
  methods: {
    //抉择文件
    upFile() {
      console.log('抉择文件...')
      my.chooseImage({
        sourceType: this.props.sourceType,
        count: this.props.maxLength - this.props.fileList.length,
        success: res => {
          //间接抛出抉择的图片的长期url数组,在父组件中解决相应上传业务
          this.props.onActive(res.apFilePaths, this.props.name)
        }
      })
    },
    //大图预览
    preViewImage(e) {
      let idx = e.currentTarget.dataset.index
      let url = this.props.fileList[idx]
      let itemType = url.split(".");
      let type = itemType[itemType.length - 1];
      if (type == 'word') {
        my.alert({
          content: '小程序临时不反对显示word类型的文件'
        });
        return
      }
      if (type == 'pdf') {
        my.downloadFile({
          url: url,
          success({ apFilePath }) {
            my.openDocument({
              filePath: apFilePath,
              fileType: 'pdf',
              success: (res) => {
                console.log('open document success')
              },
            })

          },
          fail: () => {
            console.log('err')
          }
        })
        return
      }
      my.previewImage({
        current: 0,
        urls: [url]
      })
    },
    //点击删除图标的回调
    deleteImage(e) {
      let idx = e.currentTarget.dataset.index
      // 这里间接调用props中的onDelete钩子,将索引抛出,在父组件中解决删除的逻辑
      this.props.onDelete(idx, this.props.name)
    }
  },
});
两个image就是咱们第二部筹备的两个图片😁

支付宝小程序api官网文档:https://opendocs.alipay.com/m…

最初就是款式了⛄

🆎upload.scss

.view-row {
  display: flex;
  flex-direction: row;
}

.flex-wrap{
  display: flex;
  flex-wrap: wrap;
}

.view-full{
  height:100%;
  wi

.view-half-full{
  height:50%;
  width:50%;
}

.upload{
  margin-right: 20rpx; 
  margin-bottom:20rpx;
  background:#e4e4e4;
  width:120rpx;
  height:120rpx;
  display: flex;
  justify-content: center;
  align-items: center;
  border-radius: 4rpx;
  position: relative;
}

.delete{
  position: absolute;
  top:-15rpx;
  left:105rpx;
  z-index: 99999;
  width:30rpx;
  height:30rpx;
}

四、应用示例

test.axml

<view>
  <upload 
      fileList="{{urlList}}" 
      maxLength="{{5}}" 
      name='urlList' 
      onActive="uploadSuccess" 
      onDelete='deleteImages'
>
</upload>
<view>

test.js

Page({
    data:{
        urlList:[]
    },
    ......
    uploadSuccess(resLocation, name){
       for(let i = 0;i < resLocation.length; i++){
           my.uploadFile({
             url : ...,
             header: requestUtil.createHeaders(),
             fileType: 'image',
             fileName: 'files',
             filePath: resLocation[i],
             success:res => {
                 //更新urlList
             },
             fail:() => {},
             complete:() => {}
         })
      }
    },
    deleteImages(idx, name) {
        console.log('删除图片', idx)
        let urlList = this.data[name]
        urlList.splice(idx, 1)
        this.setData({
        [name]: urlList,
    })
  },
})

上传文件的api能够查看支付宝小程序官网档:https://opendocs.alipay.com/m…

🌈默认状态

🌈上传胜利

🌈仅用作缩略图

🌈大图预览

🌈pdf预览

Props

参数 阐明 类型 默认值
name 标识符,可在钩子函数参数第二项获取 String、Number null
fileList 图片url数组 Array []
maxLength 最大上传数量 Number 5
onlyShow 是否仅用于图片展现 boolean false
sourceType 上传图片的类型,默认同时反对抉择摄像头和本地图片抉择 [] [‘camera’, ‘album’]
onActive 上传胜利时的钩子,第一个参数为本次抉择图片的长期门路数组,第二个参数为name Function (res,name) => {console.log(res,name)}
onDelete 点击删除时的钩子,第一个图片在fileList中的索引,第二个参数为name Function (res,name) => {console.log(res,name)}

完 祝安全🍻

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理