2020年不平凡的一年,终究要干不平凡的事情。
在四月份初,和几位小伙伴一起开始了开发小程序的道路,时至五月初完成了小程序1.0.0版本。
这一路走来,真的是遇到很多坑,当然也学了不少知识。在开发的道路上,难免会遇到各种各样的问题。只有靠着顽强的毅力去一点一点解决它。其中在开发小程序的核心代码时,每天脑子都是快速运转。因为开发小程序不只是一个写代码的过程,这也是一个你去思考别人的想法的过程。
在这期间,你要想完成某一个功能的时候,你要想到用户的各种骚操作,然后你需要撸码撸出各种解决这些骚操作的骚代码!!!
这些骚操作可能使你脑子有点疲惫,但是当你完成了你的这个功能,你还是会感觉自己很不错!
接下来,我就聊一聊我的小程序之旅。
一、初识小程序云开发
小萌新们不要一听云开发这三个字感觉好高大上,是不是也很难呢?对比小程序的普通开发是不是要难很多。
答案:no !!! 小程序云开发才是小萌新门应该选择的开发模式,不需要你自己搭建服务器,不需要你来运维,不需要你自己管理数据库。这些后端功能都由云开发帮你实现,你需要做的就是写前端代码:包括页面和逻辑。
还好之前有做过网页的经验,学过html和css,所以小程序的页面布局问题不是很大。可第一次接触微信小程序,这逻辑该怎样写?数据怎么存?数据怎么拿出来?数据怎么渲染到界面?一系列问题出现在我脑海中。
经过两三天的研究,我终于对小程序的逻辑有了一点认知,能写出来个123。
我研究这几天研究的是啥呢?这就是开发小程序时所用到的宝典——微信官方文档!
废话,你开发小程序不看他的官方文档你看什么?
看小程序书本?我这个过来人可以负责任的跟你讲,看书本用处不大。
看官方文档比啥都靠谱,有问题还可以在官方社区进行提问。或者直接在官方社区搜索相关问题。
整个云开发小程序,首先看官方文档数据库的增删改查,这是最基础的。然后就是一些基础的API,官方给的API有示例代码,还有专门的说明,真的是“服务很到位”。
想要使用什么功能,一般性的会有相应的API,你可直接在官方文档里搜索功能名或者API。然后找到示例代码,复制粘贴——这是一名程序员多么成熟的招牌动作!
二、进入初级撸码阶段
初级撸码阶段,每写成功一个小小的功能就觉得很不错。都会有很大的成就感!这可能是初级阶段都会有的体验吧。
接下来我将分享整个小程序比较重要的知识点以及所遇到的坑。
success:res=>{
}
fail:res=>{
}
complete:res=>{
}
这种形式是不会翻车的,当你成功调用API时,想从res参数获取数据就采用上面这种方式,而不要写成:
success(res){}
这种方式容易翻车,当res中有数据时,你想通过res获取数据,就容易有问题了。所以,建议:采用最上面那种方式!
const cloud = require('wx-server-sdk')
cloud.init()
exports.main = async (event, context) => {
const wxContext = cloud.getWXContext()
return {
event,
openid: wxContext.OPENID,
appid: wxContext.APPID,
unionid: wxContext.UNIONID,
}
}
在这个云函数中,返回结果有一项openid:wxContext.OPENID。
在调用这个js的文件的返回结果中接收到的就有用户的openID。
<view wx:if="{{isMaster}}">组件内容</view>
像上面这个就会根据isMaster是否为true来判断是否展示该组件。当然isMaster是要在这个页面的js文件中通过一些条件进行判断赋值的,赋值的时候想要渲染出效果,就需要用到下面这种setData()方法。
data:{
isMaster:false
}
this.setData({
isMaster:true
})
循环一般有两种方式:
<block wx:for="{{集合}}" wx:key="集合中的特有值">
<navigator url="path">
<view class="creatS">
</view>
</navigator>
</block>
上面这是第一种,for循环的是集合中的内容,一般是一个json格式的数据集。navigator 是用来跳转页面的,可以通过这个跳转到详情页。但是问题又来了,循环多个数据出来,如何判断点击的块跳转到的页面显示相对应的数据呢?因为在数据库中,每一条数据又有一个固定的id,云开发数据库固有的功能,所以,就是通过这个id进行判断的。但是写法该怎样写呢?往下看:
<navigator url="../path/path?id={{item._id}}"></navigator>
这样写就能跳转到特定页面了。
第二种也可以是除了block之外的view,就是说将for语句写在view里面,也是可以的,其他的跟上面的内容差不多。
db.collection('todos').doc('todo-identifiant-aleatoire').get().then(res => {
// res.data 包含该记录的数据
console.log(res.data)
this.setData({
//无效
})
})
一般通过这种方式是无效的,所以想要使用获取到的数据该怎么办?答:直接在then里面写对应的逻辑代码,直接使用res.data。
那哪种情况下使用this.setData({})有效呢?下面这种:
db.collection('todos').doc('todo-identifiant-aleatoire').get({
success: function(res) {
// res.data 包含该记录的数据
console.log(res.data)
this.setData({
//有效
})
}
})
或者
db.collection('todos').where({
_openid: 'user-open-id',
done: false
})
.get({
success: function(res) {
// res.data 是包含以上定义的两条记录的数组
console.log(res.data)
this.setData({
//有效
})
}
})
设置缓存:
wx.setStorageSync('key', dynamicValue)
其中key是改缓存的一个标识,你自己随意设置名字,稍后获取这个缓存的时候就是通过key值,dynamicValue一般是一个动态变量,也可以是固定值(需要加上单引号)
获取缓存:
var value = wx.getStorageSync('key')
这样你获取到的缓存值就存在了value当中
清除缓存:
wx.removeStorageSync('key')
清除缓存也是通过key值来识别。
<navigator url="../index/index?id={{item._id}}"></navigator>
这是传递了一个数据,我们也可以传递多个数据。例如:
<navigator url="../index/index?id={{item._id}}&school={{school}}"></navigator>
传递的这些数据,到index页面的onload()方法中添加一个参数options:
onload(options){
console.log(options)
}
传过来的数据就存放在options中。
第二种数据传递是,在js中跳转页面,将需要的值写在路径后面,示例:
wx.navigateTo({
url: '../index/index?pageid='+this.pageData,
})
当然,这种也可以传递多个值,请看示例:
wx.navigateTo({
url: '../index/index?pageid='+this.pageData+'&school='+this.data.school,
})
比较简单,也最常用的传值方式就这两种了,仅供参考。
onShow(){
this.onload()
}
wxml:
<form catchsubmit="formSubmit" catchreset="formReset">
<input class="weui-input" name="input" placeholder="这是一个输入框" />
<button type="primary" formType="submit">Submit</button>
<button formType="reset">Reset</button>
</form>
js:
formSubmit(e) {
console.log('form发生了submit事件,携带数据为:', e.detail.value)
},
这样简单的完成之后,等你点击提交按钮,输入框中的值就存在参数e中了。接着存到数据库或者是怎样,就另写逻辑代码了。
data-index="{{item._id}}"
加上这个属性,当你点击view时,就能动态的获取你点的那个view中的值。同样,也是在该view上加一个方法,在js中,该方法给个参数,这就OK了。
你想要获取的值就在这个参数中,具体位置在:
e.currentTarget.dataset.index
<button bindtap="onShareAppMessage" open-type="share">分享</button>
切记:一定要写open-type="share"这个属性,这样,此按钮才能被小程序识别出是分享按钮。接着就是bindtap=“onShareAppMessage”,这个也不要改,就写onShareAppMessage,否则不起作用哦。
js:
onShareAppMessage:function(){
return {
title: '分享页面标题',
imageUrl:'分享出去别人所看到的小程序图片',
path:'这个是别人点击你分享的小程序,进来之后的页面', //切记!此路径要以path/开头,否则无效!
success: function (res) {
console.log("转发成功:");
},
fail: function (res) {
console.log("转发失败:");
}
}
}
假如说你的一个页面有多个分享按钮,分别是不同的功能,请参考我的另外一篇文章:微信小程序之一个页面多个转发分享按钮,如何识别不同的按钮
数据库的使用
const db = wx.cloud.database()
云函数,声明数据库对象,写下面这种方式:
const db = cloud.database()
发现两者的区别没?一个有wx一个没有。这是初学者容易入的坑,在此提醒一下。
权限问题很重要,在使用数据库之前,首先看的就是权限,否则死都不知道是怎么死的。就比如,当你在查询数据的时候,查询条件根本没错,但就是返回不到结果,这时候90%的原因可能是你的数据库权限问题,没有访问数据的权限,虽然你可以将数据写进数据库,但是你拿不出来。所以,在使用之前,首要看的就是权限!!!
db.collection('todos').add({
// data 字段表示需新增的 JSON 数据
data: { //data一定不能忘记
//所添加的字段
}
})
.then(res => {
console.log(res)
})
这是新增一条数据,若是更改数据也是需要在update({})里面写上data:{},然后将要修改的字段再写进data里面。这也算是一个细节小坑,别被这些细节给打败了!
示例一:删除集合中的某一条数据。
db.collection('todos').doc('todo-identifiant-aleatoire').remove({
success: function(res) {
console.log(res.data)
}
})
或者
return await db.collection('todos').where({
//查询符合删除条件的语句
}).remove()
示例二:删除集合中某一条数据内字段数组内的某个值
db.collection('division')
.where({
openID:wxContext.OPENID,
_id:event._id
}).update({
data:{
productionImage: _.pull({
url: _.eq(event.fileID)
})
}
})
像这种,就是通过筛选和否条件的某一条数据,然后更新数组字段,通过pull方法来删除符合条件的数据值。
注:在这里,需要注意的一点是在代码中有一个下划线 _ ,这个下划线也很容易被忽略掉,这其实是声明的一个对象。
const _ = db.command
const cloud = require('wx-server-sdk') //必不可少的sdk
cloud.init() //初始化云函数一定要写在初始化数据库对象前面
const db = cloud.database()
const _ = db.command //需要用到此对象时,不要忘了声明
exports.main = async (event, context) => {
const wxContext = cloud.getWXContext()
return{
data:event
}
}
每当新增或者修改云函数中的代码之后,不要忘记点击上传,否则不生效!
大概就这些吧,能想到比较有用的就这些了,当然如果你有什么问题,可以留言给我,尽我所能帮助你!
整体来说,小程序的云开发还算是比较容易,就是坑太多,细节问题要注意,有啥问题,我能想到再补充进来!感谢你的阅读~