微信小程序开发的坑

最近做了一个小程序,顺利上线。(纯属自娱自乐,看网上说的审核不好过,就想着看运气喽,实在不行就多提两次。谁知道很快就审核过了,运气还行,不过后面提交因为进入的时候必须要授权,被要求整改)有兴趣的可以扫码体验(见文末)。这里我总结分享一下我遇到的坑,以及还没有解决的问题(文中方法不一定最优),欢迎大家留言讨论

数据库权限

我是用云开发自带的数据库来存储数据(当然你可以用自己的,我没这么做,所以不参与讨论),那么这就存在一个问题,数据库的默认权限是:仅创建者可读写。然后在页面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,看到网上有人说后面这个(我就被这个误导了),希望大家不要再被误导了,是前面那个

两个定时器

  1. 我做的是个类定时器工具,直接用到了计时器
//启动计时器
var interval = setInterval(
       function () {
         xxx//每一秒执行
       }, 1000);
//清除计时器
clearInterval(interval)

这个计时器存在一个问题,小程序切到后台,它就停止工作了,进入前台才会工作。

解决办法:
a.在onHide方法里面停止计时器,并记下停止时的时间戳
b.在onShow方法里开启计时器,并加上停止的时间

  1. 用到了倒计时工具,因为页面有个打卡按钮,打卡后字会变;所以设置了这个倒计时,设置了现在到下一天凌晨的时间间隔后,将按钮的字和状态变掉
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个小时。你问我问什么要转东八区时间,因为我看到了时间不一致,病急乱投医。

Tom和Jerry的时光

posted @ 2019-11-11 23:56  少年小白  阅读(532)  评论(0编辑  收藏  举报