微信小程序开发的坑
最近做了一个小程序,顺利上线。(纯属自娱自乐,看网上说的审核不好过,就想着看运气喽,实在不行就多提两次。谁知道很快就审核过了,运气还行,不过后面提交因为进入的时候必须要授权,被要求整改)有兴趣的可以扫码体验(见文末)。这里我总结分享一下我遇到的坑,以及还没有解决的问题(文中方法不一定最优),欢迎大家留言讨论
数据库权限
我是用云开发自带的数据库来存储数据(当然你可以用自己的,我没这么做,所以不参与讨论),那么这就存在一个问题,数据库的默认权限是:仅创建者可读写。然后在页面js里面很可能就获取、修改不了数据,也就是除了你,其他人访问页面都访问不了数据。
ps:我有一次忘了这个,然后找哪里出问题了查不到数据,查了好久
解决方法:
a. 更改数据库的权限,使其能够读或写
b. 对于操作数据库的动作全放到云函数中去
动态监听数据库
我有一个好友列表,希望动态看到好友状态,所以监听好友状态变化了,就重新获取好友列表
//创建监听器
const watcher = db.collection('T_STATUS').where({
openId: db.command.in(friendsId)
}).field({//只监听这个字段
updateDate: true
}).watch({
onChange: function (snapshot) {
xxx
},
onError: function (err) {
console.error('the watch closed because of error', err)
}
})
}
//关闭监听器
watcher.close()
本着监听应该保证获取最少数据的原则,我只监听了所有好友的updateDate这个字段。然后在用户任何状态变化的时候都更新这个字段,达到有效监听
数据库的联表查询
其实也不属于联表查询了,表A是用户表,表B是用户的好友表,表c是消息记录表。用以下方法一次性查出每个好友发送给你的消息数。不过,该方法显得很笨拙。
var friendList = []
//获取关联的好友详细信息
for (let i = 0, length = friends.length; i < length; ++i) {
await Promise.all([
db.collection('T_A').where({
openId: friends[i].friendId,
}).get(),
db.collection('T_B').where({
openId: friends[i].friendId
}).get(),
db.collection('T_C').where({//好友发给自己的未读消息数
sendFrom: friends[i].friendId,
sendTo: friends[i].ownId,
readed: false
}).count()
]).then(([user, status, num]) => {
event.friendList.push({
...friends[i],
user: user.data[0],
status: status.data[0],
unreadNum: num.total
})
}).catch(err => {
console.log(err)
})
}
页面引入定义的工具函数
在wxs文件(/utils/app.wxs)中定义函数
var formatTime = function (time) {
return (time/60 > 9 ? parseInt(time/60) : "0"+parseInt(time/60)) + ":" + (time%60 > 9 ? time%60 : "0"+time%60);
}
// 要引用这个文件的函数或者变量,除了在要引用的的js文件中模块化之外(var utils=require('js地址')),
// 在被引用的的js中要通过 module.exports={a:a}作为面向对象的变量输出函数如下:
module.exports = {
formatTime: formatTime
}
在wxml文件中引入工具函数就可以使用
<wxs src="../../utils/app.wxs" module="utils" />
{{utils.formatTime()}}
再记两个不错的工具
1.日历插件:https://github.com/bingyang519/wxMiniProgram.git
2.图表插件:https://blog.csdn.net/weixin_40709898/article/details/81020562
注:图表插件的折线图选curve线型,两个数值相差较大,会出现正值跑到负轴的情况
用到的几个页面加载方法
onLoad:监听页面加载
onShow:监听页面显示
onHide:监听页面隐藏
onUnload:监听页面卸载
onShareAppMessage:用户点击右上角转发,或者控件有open-type="share"
分享应用
主要是自定义图片,这个没啥技巧性
//分享应用给好友
onShareAppMessage: function (options) {
var that = this;
var shareObj = {
title: "这是一个小程序",
path: '/pages/index/index', // 默认是当前页面,必须是以‘/’开头的完整路径
imageUrl: '/images/sharePhoto.png',
}
return shareObj;
}
主要说一下的是imageURL, 不是imgURL,看到网上有人说后面这个(我就被这个误导了),希望大家不要再被误导了,是前面那个
两个定时器
- 我做的是个类定时器工具,直接用到了计时器
//启动计时器
var interval = setInterval(
function () {
xxx//每一秒执行
}, 1000);
//清除计时器
clearInterval(interval)
这个计时器存在一个问题,小程序切到后台,它就停止工作了,进入前台才会工作。
解决办法:
a.在onHide方法里面停止计时器,并记下停止时的时间戳
b.在onShow方法里开启计时器,并加上停止的时间
- 用到了倒计时工具,因为页面有个打卡按钮,打卡后字会变;所以设置了这个倒计时,设置了现在到下一天凌晨的时间间隔后,将按钮的字和状态变掉
timer = setTimeout(function () {
xxx//下一天的凌晨执行
}, twelveClock);
这个遇到的问题是怎么也获不到东八区和下一天凌晨的时间
解决办法:
a东八区时间:后文有提到,还未解决
b下一天凌晨时间:var nextday = new Date(new Date(date.getTime() + 10006060*24).setHours(0,0,0,0));
列表里的输入和发送事件
我在好友列表里的每一行都,放了一个输入框和发送按钮,因为好友列表是动态的,所以这些事件也都是动态的,这种页面实现这个功能还是有点儿挑战的。
首先,动态列表就存在遍历list,它的默认下标index可一个取到。控件存在data-key属性,key对应变量名,在触发事件里可以得到传过去的值;input控件存在一个bindInput属性,可以配一个方法,监听输入事件
//wxml
<view class="friends" wx:for="{{friendList}}"
<view class="message">
<input class="weui-input" maxlength="200" placeholder="留言..." adjust-position="true" data-index="{{index}}" bindinput="messageInput" value="{{item.message}}"/>
</view>
<view class="send" bindtap="send" data-index="{{index}}">
<image src="/images/send.png"></image>
</view>
</view>
//js
messageInput: function(event) {
//console.log(event.currentTarget.dataset)
var index = event.currentTarget.dataset.index
this.data.friendList[index].message = event.detail.value
this.setData({
friendList: this.data.friendList
})
},
//发送消息
send: function(event) {
//console.log(event.currentTarget.dataset)
var index = event.currentTarget.dataset.index
console.log(this.data.friendList[index].message)
...
}
未解决的问题
云函数中的日期时区问题:
在云函数中用到日期的时候,我将new Date()转成东八区时间(至于怎么转,大家可以百度),这时候就存在了三个不同的时间:1.云函数打印日志的时间是北京时间前8个小时;2.我转的时间是北京时间;3.把我转的时间存到数据库,显示的是北京时间加上8个小时。你问我问什么要转东八区时间,因为我看到了时间不一致,病急乱投医。