1、布局樣式
在正式自定義上傳前我們先將靜態(tài)頁(yè)面搭建好。
樣式代碼:
<template>
<view>
<view class="content">
<view class="images" v-for="(item,index) in 5" :key="index">
<image class="img" src="../../static/logo.png" mode="aspectFill"></image>
<view class="remove">x</view>
</view>
<view class="files" @click="addFiles">
<view class="add">+</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'Hello'
}
},
onLoad() {
},
methods: {
}
}
</script>
<style lang="scss" scoped>
.content {
padding: 30rpx;
display: flex;
flex-wrap: wrap;
.files {
width: 200rpx;
height: 200rpx;
background-color: #f7f7f7;
color: #6d6d6d;
font-size: 100rpx;
font-weight: 100;
display: flex;
justify-content: center;
align-items: center;
margin: 10rpx;
}
.images {
width: 200rpx;
height: 200rpx;
margin: 10rpx;
position: relative;
.img {
width: 100%;
height: 100%;
}
.remove {
width: 50rpx;
height: 50rpx;
background-color: #f7f7f7;
position: absolute;
top: -5rpx;
right: -10rpx;
text-align: center;
opacity: .5;
border-radius: 0 0 0 50rpx;
color: #c5c5c5;
}
}
}
</style>
2、使用uniappAPI(uni.chooseImage)
通過uniapp的uni.chooseImage從本地相冊(cè)選擇圖片或使用相機(jī)拍照。
在data中定義一個(gè)響應(yīng)式數(shù)據(jù)來接收我們選擇的圖片,然后通過v-for渲染到我們的頁(yè)面,達(dá)到縮略圖的效果。
代碼:
<template>
<view>
<view class="content">
<view class="images" v-for="(item,index) in tempFiles" :key="index">
<image class="img" :src="item.path" mode="aspectFill"></image>
<view class="remove">x</view>
</view>
<view class="files" @click="addFiles">
<view class="add">+</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
tempFiles:[]
}
},
onLoad() {
},
methods: {
addFiles() {
uni.chooseImage({
count: 9, // 最大選擇的張數(shù),默認(rèn)是九張,可以不寫
success:res=>{
console.log(res);
// 接受選擇的圖片數(shù)組
this.tempFiles= res.tempFiles
}
})
}
}
}
</script>
效果:
3、解決bug和添加功能
3.1 bug1
最初我們定義了只能選擇九張圖片,然而這個(gè)時(shí)候上圖中的+(選擇圖片)還在,我們應(yīng)該在選擇了九張圖片之后將它隱藏。
我們只需要加個(gè)判斷即可
<view class="files" @click="addFiles" v-if="tempFiles.length < 9">
<view class="add">+</view>
</view>
3.2 bug2
在我們選擇了五張,在想多加幾張圖片時(shí)會(huì)發(fā)現(xiàn)之后選擇的圖片會(huì)將之前的圖片覆蓋,所有我們要將圖片進(jìn)行拼接。
uni.chooseImage({
count: 9, // 最大選擇的張數(shù),默認(rèn)是九張,可以不寫
success: res => {
console.log(res);
// 接受選擇的圖片數(shù)組
this.tempFiles = [...this.tempFiles, ...res.tempFiles]
})
3.3 bug3
如果第一次選擇八張,然后在選擇圖片,會(huì)超過原本我們只想要的九張照片,所有我們要對(duì)它進(jìn)行截取。
uni.chooseImage({
count: 9, // 最大選擇的張數(shù),默認(rèn)是九張,可以不寫
success: res => {
console.log(res);
// 接受選擇的圖片數(shù)組
let oldImg = [...this.tempFiles, ...res.tempFiles]
// console.log(oldImg);
let newImg = oldImg.slice(0, 9)
// console.log(newImg);
// 在賦值前進(jìn)行截取
this.tempFiles = newImg
}
})
3.4 點(diǎn)擊圖片進(jìn)行預(yù)覽
通過uniapp的API(uni.previewImage)我們來完成預(yù)覽圖片這個(gè)功能。
<image @click="previewImg(index)" class="img" :src="item.path" mode="aspectFill"></image>
給每張圖片添加一個(gè)點(diǎn)擊事件,將自身的索引值傳遞過去。
// 預(yù)覽圖片
previewImg(index) {
// console.log(this.tempFiles);
// 過濾
let imgUrl = this.tempFiles.map(item => item.path)
// console.log(imgUrl);
uni.previewImage({
current: index, //點(diǎn)擊的索引值
urls: imgUrl,
})
}
由于我們的數(shù)據(jù)是這樣的數(shù)組對(duì)象,所以要對(duì)其進(jìn)行過濾,得到一個(gè)只有地址的數(shù)組。
3.5 刪除圖片
給每個(gè)刪除按鈕添加點(diǎn)擊事件,并將索引值傳遞過去。
<view class="remove" @click="removeImg(index)">x</view>
// 刪除圖片
removeImg(index) {
this.tempFiles.splice(index, 1)
}
4、云函數(shù)上傳到云存儲(chǔ)
我們先來講上傳按鈕的樣式搭建一下。
<template>
<view>
<view class="content">
<view class="images" v-for="(item,index) in tempFiles" :key="index">
<image @click="previewImg(index)" class="img" :src="item.path" mode="aspectFill"></image>
<view class="remove" @click="removeImg(index)">x</view>
</view>
<view class="files" @click="addFiles" v-if="tempFiles.length<9">
<view class="add">+</view>
</view>
</view>
<button class="upload" :disabled="tempFiles.length > 0 ? false : true">發(fā)表</button>
</view>
</template>
<style lang="scss" scoped>
.upload {
position: absolute;
top: -50rpx;
right: 20rpx;
width: 120rpx;
height: 60rpx;
line-height: 60rpx;
background-color: #04c062;
color: white;
border-radius: 10rpx;
text-align: center;
font-size: 30rpx;
}
.content {
padding: 30rpx;
margin-top: 70rpx;
display: flex;
flex-wrap: wrap;
.files {
width: 200rpx;
height: 200rpx;
background-color: #f7f7f7;
color: #6d6d6d;
font-size: 100rpx;
font-weight: 100;
display: flex;
justify-content: center;
align-items: center;
margin: 10rpx;
}
.images {
width: 200rpx;
height: 200rpx;
margin: 10rpx;
position: relative;
.img {
width: 100%;
height: 100%;
}
.remove {
width: 50rpx;
height: 50rpx;
background-color: #f7f7f7;
position: absolute;
top: -5rpx;
right: -10rpx;
text-align: center;
opacity: .5;
border-radius: 0 0 0 50rpx;
color: #c5c5c5;
}
}
}
</style>
效果:
客戶端上傳文件到云函數(shù)、云函數(shù)再上傳文件到云存儲(chǔ),這樣的過程會(huì)導(dǎo)致文件流量帶寬耗費(fèi)較大。
所以一般上傳文件都是客戶端直傳。
添加點(diǎn)擊事件
<button @click="uploadFn" class="upload" :disabled="tempFiles.length > 0 ? false : true">發(fā)表</button>
默認(rèn)一次只能上傳一個(gè)后面我們進(jìn)行循環(huán)上傳。
// 上傳到云存儲(chǔ)
uploadFn() {
console.log(this.tempFiles);
uniCloud.uploadFile({
filePath: this.tempFiles[0].path,
cloudPathAsRealPath: true, //讓cloudPath作為文件存儲(chǔ)路徑
cloudPath: "images/" + this.tempFiles[0].name //上傳到images文件夾下
}).then(res => {
console.log(res);
})
}
上傳成功:
<button @click="goUpload" class="upload" :disabled="tempFiles.length > 0 ? false : true">發(fā)表</button>
goUpload() {
this.tempFiles.forEach(item=>{
this.uploadFn(item)
})
},
// 上傳到云存儲(chǔ)
uploadFn(item) {
uniCloud.uploadFile({
filePath: item.path,
cloudPathAsRealPath: true, //讓cloudPath作為文件存儲(chǔ)路徑
cloudPath: "images/" + item.name //上傳到images文件夾下
}).then(res => {
console.log(res);
})
}
這樣就完成了上傳多張圖片的功能,不過我們的圖片地址后面還要存儲(chǔ)到數(shù)據(jù)庫(kù)中,所以我們將其改成promise的形式,監(jiān)聽全部上傳完后,然后存儲(chǔ)到數(shù)據(jù)庫(kù)中。
goUpload() {
let promissState = this.tempFiles.map(async item => {
return await this.uploadFn(item)
})
// console.log(promissState);
Promise.all(promissState).then(res => {
// console.log(res);
let imgUrl = res.map(item => item.fileID)
// console.log(imgUrl);
const objImg = {...imgUrl}
this.uploadDataBase(objImg)
}).catch(e => {
console.log(e);
})
},
// 上傳到云存儲(chǔ)
uploadFn(item) {
return uniCloud.uploadFile({
filePath: item.path,
// cloudPathAsRealPath: true, //讓cloudPath作為文件存儲(chǔ)路徑
// cloudPath: "images/" + item.name //上傳到images文件夾下
cloudPath: item.name,
//文件夾模式,不允許文件覆蓋
})
},
// 上傳到數(shù)據(jù)庫(kù)
uploadDataBase(objImg) {
uniCloud.callFunction({
name: 'uploadDataBase',
data: objImg
}).then(res => {
console.log(res);
})
}
云函數(shù)文章來源:http://www.zghlxwxcb.cn/news/detail-651353.html
'use strict';
const db = uniCloud.database()
exports.main = async (event, context) => {
const data = await db.collection('images').add(event)
return data
};
最終代碼:文章來源地址http://www.zghlxwxcb.cn/news/detail-651353.html
<template>
<view>
<view class="content">
<view class="images" v-for="(item,index) in tempFiles" :key="index">
<image @click="previewImg(index)" class="img" :src="item.path" mode="aspectFill"></image>
<view class="remove" @click="removeImg(index)">x</view>
</view>
<view class="files" @click="addFiles" v-if="tempFiles.length<9">
<view class="add">+</view>
</view>
</view>
<button @click="goUpload" class="upload" :disabled="tempFiles.length > 0 ? false : true">發(fā)表</button>
</view>
</template>
<script>
export default {
data() {
return {
tempFiles: [],
}
},
onLoad() {
},
methods: {
addFiles() {
uni.chooseImage({
count: 9, // 最大選擇的張數(shù),默認(rèn)是九張,可以不寫
success: res => {
// console.log(res);
// 接受選擇的圖片數(shù)組
let oldImg = [...this.tempFiles, ...res.tempFiles]
// console.log(oldImg);
let newImg = oldImg.slice(0, 9)
// console.log(newImg);
this.tempFiles = newImg
}
})
},
// 預(yù)覽圖片
previewImg(index) {
// console.log(this.tempFiles);
// 過濾
let imgUrl = this.tempFiles.map(item => item.path)
// console.log(imgUrl);
uni.previewImage({
current: index, //點(diǎn)擊的索引值
urls: imgUrl,
})
},
// 刪除圖片
removeImg(index) {
this.tempFiles.splice(index, 1)
},
goUpload() {
let promissState = this.tempFiles.map(async item => {
return await this.uploadFn(item)
})
// console.log(promissState);
Promise.all(promissState).then(res => {
// console.log(res);
let imgUrl = res.map(item => item.fileID)
// console.log(imgUrl);
const objImg = {...imgUrl}
this.uploadDataBase(objImg)
}).catch(e => {
console.log(e);
})
},
// 上傳到云存儲(chǔ)
uploadFn(item) {
return uniCloud.uploadFile({
filePath: item.path,
// cloudPathAsRealPath: true, //讓cloudPath作為文件存儲(chǔ)路徑
// cloudPath: "images/" + item.name //上傳到images文件夾下
cloudPath: item.name,
//文件夾模式,不允許文件覆蓋
})
},
// 上傳到數(shù)據(jù)庫(kù)
uploadDataBase(objImg) {
uniCloud.callFunction({
name: 'uploadDataBase',
data: objImg
}).then(res => {
console.log(res);
})
}
}
}
</script>
<style lang="scss" scoped>
.upload {
position: absolute;
top: -50rpx;
right: 20rpx;
width: 120rpx;
height: 60rpx;
line-height: 60rpx;
background-color: #04c062;
color: white;
border-radius: 10rpx;
text-align: center;
font-size: 30rpx;
}
.content {
padding: 30rpx;
margin-top: 70rpx;
display: flex;
flex-wrap: wrap;
.files {
width: 200rpx;
height: 200rpx;
background-color: #f7f7f7;
color: #6d6d6d;
font-size: 100rpx;
font-weight: 100;
display: flex;
justify-content: center;
align-items: center;
margin: 10rpx;
}
.images {
width: 200rpx;
height: 200rpx;
margin: 10rpx;
position: relative;
.img {
width: 100%;
height: 100%;
}
.remove {
width: 50rpx;
height: 50rpx;
background-color: #f7f7f7;
position: absolute;
top: -5rpx;
right: -10rpx;
text-align: center;
opacity: .5;
border-radius: 0 0 0 50rpx;
color: #c5c5c5;
}
}
}
</style>
到了這里,關(guān)于uniapp實(shí)現(xiàn)自定義上傳圖片的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!