一、序言
上传图片以及大图预览应该是小程序中比较常用的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
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
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)} |
完 祝平安