貼幾個可在線訪問的圖片數據,圖片數據最好包含id、url、loading、success的狀態
分別對應:
id === keyurl === urlloading === 上傳中success === 上傳成功的狀態
const imgList = ref([
{ id:1, url: 'https://fastly.jsdelivr.net/npm/@vant/assets/apple-2.jpeg', loading: false, success: true },
{ id:2, url: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg', loading: true, success: true },
{ id:3, url: 'https://fastly.jsdelivr.net/npm/@vant/assets/apple-1.jpeg', loading: false, success: false },
{ id:4, url: 'https://fastly.jsdelivr.net/npm/@vant/assets/apple-3.jpeg', loading: false, success: true }
]);
這裏沒有用任何ui庫的上傳組件,使用uniapp內置api實現
1、uni.chooseMedia選取文件
2、uni.uploadFile上傳文件
3、上傳後添加imgList數據
頁面結構
<view @click="onPickerFile">圖片上傳</view>
選取文件
<script setup>
const onPickerFile = () => {
// 最多選取9張,類型為image,可以拍攝或選取相冊,視頻類型最長30秒,默認後置攝像頭
uni.chooseMedia({
count: 9,
mediaType: ['image'],
sourceType: ['album', 'camera'],
maxDuration: 30,
camera: 'back',
success(res) {
// res.tempFiles是一個數組,內含選取的文件臨時路徑
console.log(res.tempFiles);
// 遍歷上傳每一張,這樣做是為了單獨管理圖片的loading狀態,你也可以一次性上傳多張
res.tempFiles.forEach((item) => {
uoloadFile(item);
});
},
fail(err) {
console.log('選取失敗', err);
}
});
};
</script>
上傳文件
<script setup>
const imgList = ref([]);
const uoloadFile = (itemFile) => {
// 生成一個隨機數id,這裏最好用uuid
let fileId = String(Math.random())
// 上傳前先默認將臨時路徑添加到列表,loading中
imgList.value.push({
id: fileId,
url: itemFile.tempFilePath,
loading: true,
success: true
});
uni.uploadFile({
url: `https://test/uploadFiles`, //僅為示例,非真實的接口地址
filePath: itemFile.tempFilePath, // 這裏為圖片臨時路徑
name: 'files', // 後端接口接的參數,比如Request body參數為:files:array<string>
header: {
'content-type': 'multipart/form-data',
authorization: `你的token`
},
success: (res) => {
// 上傳完成,根據id匹配到我們剛才預先添加的圖片項
const targetItem = imgList.value.find((item) => item.id === fileId);
if (res.statusCode == 200) {
// uni.uploadFile上傳完成後,data數據是序列化的,這裏反序列化取出來
let data = JSON.parse(res.data);
// 更新圖片項的url、loading、success
targetItem.url = data.data[0];
targetItem.loading = false;
targetItem.success = true;
} else {
// 如果上傳失敗,則置空url、success為false
// 頁面上可根據 !laoding && !success 顯示上傳失敗
targetItem.url = '';
targetItem.loading = false;
targetItem.success = false;
}
},
fail(err) {
console.log('上傳失敗', err);
// 找出當前對應的圖片項
const targetItem = imgList.value.find((item) => item.id === fileId);
// 如果上傳失敗,則置空url、success為false
// 頁面上可根據 !laoding && !success 顯示上傳失敗
targetItem.url = '';
targetItem.loading = false;
targetItem.success = false;
}
});
};
};
</script>
上傳後返回的數據示例
你的頁面結構應該有如下幾個要素
<template>
<view>
// 遍歷渲染
<view v-for="(item, index) in imgList" :key="item">
// 圖片
<image mode="aspectFill" :src="item.url" @click="onImage(item)" />
// 蒙層,用於上傳中、上傳失敗,絕對定位,覆蓋整個圖片上方
<view class="img-mask" v-if="item.loading || !item.success">
// 上傳的loading,根據v-if="item.loading"判斷
<uni-load-more :showText="false" color="#f7f7f7" iconType="circle" :status="'loading'" v-if="item.loading" />
// 如果上傳失敗,則在蒙層內顯示,根據v-if="!item.loading && !item.success"判斷
<view class="loading-text" v-if="!item.loading && !item.success">上傳失敗</view>
</view>
// 刪除按鈕,上傳中禁用刪除,絕對定位,在圖片的右上角
<view class="close-btn" v-if="!item.loading" @click="onDeleteImage(item)">
刪除
</view>
</view>
</view>
</template>
圖片刪除
const onDeleteImage = (item) => {
let index = imgList.value.findIndex((img) => img.url === item.url);
if (index == -1) return;
imgList.value.splice(index, 1);
};
圖片預覽
const onImage = (e) => {
// 得到url數組
let urls = imgList.value.filter((item) => !item.loading && item.success).map((item) => item.url);
// 當前圖片的index
let index = urls.findIndex((url) => url == e.url);
// 預覽
uni.previewImage({
urls,
current: index
});
};
參考資料:
uni.chooseMedia
uni.previewImage
uni.uploadFile
image