本文主要聊聊該項目的雲開發技術點和js邏輯,IM即時通信以後會寫。經過本文你將學習微信小程序雲函數的使用、組件間通訊的各類方法、根據功能需求設計js邏輯、promise相關用法、頁面分頁加載等。
github項目地址javascript
promise.all
實現先上傳圖片,拿到圖片的雲路徑後,再將用戶輸入的發佈信息所有上傳。inputDetail
中的方法checkUploadForm
(帶參數releaseType
,方便後面上傳數據是添加到失物招領的found
集合仍是尋物啓事的lost
集合),表單內容不爲空開始上傳;forEach
,將每張圖片的緩存路徑傳遞給promise
函數promiseUplodImg
(函數resolve
上傳完成後每張圖片的雲路徑)上傳圖片;push
進一個數組中,再執行promise.all
(該方法接收一個每一項都是promise函數的數組);.then
(接收一個數組,包含全部圖片的雲路徑)將用戶輸入的信息上傳。// miniprogram/pages/release/release.js
data: {
clickStatus: 0,
releaseTypes: ['found', 'lost'],
}
//當即發佈按鈕上綁定該方法
checkUploadForm: function () {
let that = this
this.setData({
isUpload: true
}) // 聲明上傳狀態
this.inputDetail = this.selectComponent('#inputDetail')
this.inputDetail.checkUploadForm(that.data.releaseTypes[that.data.clickStatus])
//調用組件inputDetail上的checkUploadForm方法,傳參found || lost
}
複製代碼
// // components/inputDetail/inputDetail.js
checkUploadForm(releaseType) {
//releaseType 根據參數肯定發佈的類型是失物招領仍是尋物啓事
let that = this
let promises = []
if (that.data.releaseText && that.data.thingsType) {
that.setData({
releaseType,
})
if (that.data.imgLocalPath.length > 0) {
wx.showLoading({
title: '正在發佈...'
});
that.data.imgLocalPath.forEach(element => {
promises.push(that.promiseUplodImg(element))
})
// 遍歷緩存圖片路徑,將多個promise函數放入數組promises中
// 拿到全部圖片的雲路徑
Promise.all(promises)
.then((imgCloudPath) => {
console.log(imgCloudPath);
that.uploadRelease(imgCloudPath)
})
.catch((err) => { console.log(err); })
} else {
//用戶沒有選擇圖片,則直接上傳發布信息
that.uploadRelease()
}
} else {
wx.showToast({
title: '內容或分類爲空',
image: '../../asserts/icons/my_icon_still@2x.png',
duration: 1800
})
}
},
promiseUplodImg(element) {
return new Promise((resolve, reject) => {
//一次只能上傳一張圖片到數據庫
const filePath = element;
let a = filePath.lastIndexOf('.');
let b = filePath.lastIndexOf('.', a - 1);
let c = filePath.substring(b + 1, a);
const cloudPath = c + filePath.match(/\.[^.]+?$/);
wx.cloud.uploadFile({
filePath,
cloudPath,
success: (res) => {
console.log('上傳成功', res)
resolve(res.fileID)
//每張圖片的雲路徑
},
fail: (err) => {
console.log('上傳失敗', err)
}
});
})
},
uploadRelease(imgCloudPath) {
let that = this
wx.cloud.callFunction({
name: "uploadInput",
data: {
releaseType: that.data.releaseType,
releaseImg: imgCloudPath,
releaseText: that.data.releaseText,
thingsType: that.data.thingsType,
releaseCall: that.data.releaseCall,
releaseRemind: that.data.releaseRemind,
//用戶輸入的所有信息
},
success: () => {
wx.hideLoading();
const releaseType = that.data.releaseType
wx.switchTab({
url: `/pages/${releaseType}/${releaseType}`
})
// 跳轉到發佈類型對應的頁面
wx.hideNavigationBarLoading()
},
fail: (err) => {
console.log(err);
},
complete: () => {
that.setData({
releaseText: '',
imgLocalPath: [],
thingsType: '',
releaseCall: '',
releaseRemind: false,
releaseType: 'found',
typeIndex: 0,
})
}
})
},
複製代碼
promise
先將發佈的信息上傳至對應的集合,再將發佈記錄的id
和發佈者的openId
上傳至集合user-release
。這樣存儲便於後面讀取數據渲染界面,每一條發佈記錄的id
經過user-release
集合與發佈者信息綁定在一塊兒。(id是雲開發數據庫中給每條記錄自動生成的_id)// 雲函數uploadInput
const getTime = function () {
return new Promise((resolve, reject) => {
var now = new Date();
var month = now.getMonth() + 1;
var day = now.getDate();
var hour = now.getHours() + 8; //沒加8被坑
var minute = now.getMinutes();
var time = ''
if (month < 10) time += "0";
time += month + "-";
if (day < 10) time += "0";
time += day + " ";
if (hour < 10) time += "0";
time += hour + ":";
if (minute < 10) time += '0';
time += minute;
resolve(time)
})
}
exports.main = async (event, context) => {
const userInfo = event.userInfo
const createTime = await getTime()
return await db.collection(event.releaseType).add({
data: {
releaseType: event.releaseType,
releaseImg: event.releaseImg,
releaseText: event.releaseText,
thingsType: event.thingsType,
releaseCall: event.releaseCall,
releaseRemind: event.releaseRemind,
createBy: userInfo.openId,
createTime: createTime,
deleted: false
}
})
.then(res => {
return db.collection('user-release').add({
data: {
releaseId: res._id,
userId: userInfo.openId,
deleted: false,
}
})
})
}
複製代碼
getRelease
,並將獲取到的頁面數據存入一箇中間變量middleArr
(這樣便於作分頁/分類加載);showPage
判斷當前點擊的類別,從middleArr
中篩選出與點擊類別匹配的數據,並將數據放入releaseIndo
傳給組件infoCard
來展現用戶發佈的信息。// components/infoCard/infoCard.js
// 獲取到的數據傳入組件進行渲染
properties: {
releaseInfo: {
type: Array,
value: []
}
<!--components/infoCard/infoCard.wxml -->
<block wx:for="{{releaseInfo}}" wx:key="index" wx:for-item="releaseItem"> </block>
複製代碼
<!--miniprogram/pages/found/found.wxml 發佈信息展現頁-->
<view class="navbar">
<scroll-view scroll-x="{{true}}">
<category tabs="{{['所有','證件','書籍文具','電子設備','生活用品','其餘']}}" catch:onTitleChange="onTitleChange"></category>
</scroll-view>
</view>
<view class="foundContent">
<view class="inforCards">
<infocard id="infoCard" class="infoCard" releaseInfo="{{releaseInfo}}"></infocard>
</view>
</view>
複製代碼
// miniprogram/pages/found/found.js
data: {
tabbarText: 'found',
releaseInfo: [], // 傳遞給組件的數據
typeTitle: ['all', 'card', 'booktool', 'electroic', 'lifetool', 'others'],
thingsType: 'all', //默認點擊的是‘所有’類
middleArr: [],
},
onTitleChange(e) {
//判斷用戶點擊的類別
this.setData({
thingsType: this.data.typeTitle[e.detail]
})
this.showPage()
},
onShow: function () {
//加載頁面,調用雲函數
let that = this
wx.showNavigationBarLoading();
wx.cloud.callFunction({
name: 'getRelease',
data: {
tabbarText: that.data.tabbarText,
//根據點擊的tabbar=失物招領或尋物啓事,獲取不一樣集合中的數據
},
success: res => {
that.setData({
middleArr: res.result,
//成功返回的數據放入中間變量
})
that.showPage()
},
fail: (err) => {
console.log(err)
},
complete: () => {
wx.hideNavigationBarLoading()
}
})
},
showPage() {
let that = this
if (that.data.thingsType == 'all') {
//若是點擊的是‘所有’,則直接將中間變量中的數據傳給releaseInfo,組件獲取數據進行渲染
that.setData({
releaseInfo: that.data.middleArr
})
} else {
let newArr = []
const val = that.data.thingsType
//不然遍歷中間變量中的數據,將知足條件的數據傳給組件
that.data.middleArr.forEach(item => {
if( item.thingsType == val){
newArr.push(item)
}
})
that.setData({
releaseInfo: newArr
})
}
},
複製代碼
getRelease
,在集合user-release
中篩選出未刪除數據(獲得一個數組,數組每一項都是一個對象,每一個對象中包含每一發布信息的releaseId
和與之對應的發佈者openId
);releaseId
字段,根據該字段上的內容和未刪除deleted:false
在集合found || lost
中篩選出對應失物招領或尋物啓事的發佈信息;createBy
字段,在集合goodUser
中篩選出對應的發佈者信息,並將每條發佈者信息放入發佈信息的createBy
中;unshift
進入數組returnResult
中(保證將最新的發佈信息渲染在最前面),返回returnResult
。// 雲函數getRelease
exports.main = async (event, context) => {
let releaseList = await db.collection('user-release')
.where({
deleted: false
})
.get()
let returnResult = []
for (let item of newReleaseList) {
const oneRelease = await db.collection(event.tabbarText)
// 調用雲函數傳入 event.tabbarText=found||lost
// 在found || lost 集合中獲取數據
.where({
_id: item.releaseId,
deleted: false
})
.get()
// 通過上面的代碼篩選,newReleaseList中可能存在空項
// 能夠直接返回returnResult.push(oneRelease.data)進行查看理解
if (oneRelease.data.length > 0) {
const userInfo = await db.collection('goodUser')
.where({
openId: oneRelease.data[0].createBy
})
.get()
oneRelease.data[0].createBy = userInfo.data[0];
returnResult.unshift(oneRelease.data[0])
}
}
return returnResult
}
複製代碼
onShow
;getRelease
再次請求數據,將返回的數據傳遞給組件渲染;getRelease
中,將獲取的數組使用slice
方法,slice
接受的參數爲:- (當前頁 * 每次獲取數) ,用參數newRelease
接收該方法返回的新數組。新數組中將是最新的(當前頁 * 每次獲取數)條發佈信息。// miniprogram/pages/found/found.js
onReachBottom: function () {
this.setData({
currentPage: this.data.currentPage + 1
})
console.log(this.data.currentPage);
this.onShow()
},
wx.cloud.callFunction({
name: 'getRelease',
data: {
tabbarText: that.data.tabbarText,
currentPage: that.data.currentPage
},
......
複製代碼
// 雲函數 getRelease
let releaseList = await db.collection('user-release')
.where({
deleted: false
})
.get()
const currentPage = event.currentPage
const releaseSize = 4
const sliceRelease = releaseSize * currentPage
const newReleaseList = releaseList.data.slice(-sliceRelease)
// 在這裏插入實現分頁加載
let returnResult = []
for (let item of newReleaseList) {
const oneRelease = await db.collection(event.tabbarText)
.where({
........
複製代碼
properties
,也能夠嘗試selectComponent
來調用組件上的方法,將數據傳過去。