本文主要聊聊该项目的云开发技术点和js逻辑,IM即时通信以后会写。经过本文你将学习微信小程序云函数的使用、组件间通讯的各类方法、根据功能需求设计js逻辑、promise相关用法、页面分页加载等。
github项目地址javascript
promise.all
实现先上传图片,拿到图片的云路径后,再将用户输入的发布信息所有上传。实现:html
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, } }) }) }
实现:java
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
来调用组件上的方法,将数据传过去。